From e90b8716c2ef2ed545f3dc53651253d54f0b604d Mon Sep 17 00:00:00 2001 From: David Festal Date: Tue, 18 Aug 2026 20:34:01 +0200 Subject: [PATCH 1/4] feat(prepare-sources): implement generate-manifests pipeline module Generate manifest.json (workspace package inventory) and, when the workspace contains backstage:^ dependencies, backstage-manifest.json with @backstage package metadata extracted from yarn.lock and validated against versions.backstage.io. Add a zero-dependency Yarn Berry lockfile parser/serializer for round-trip fidelity, shared manifest types, and fixture-based tests. Extend test utilities with a mockFetch helper and wire the module into the pipeline runner. Add @vitest/coverage-v8 and ignore the coverage directory. Assisted-by: Cursor Signed-off-by: David Festal --- .sonarcloud.properties | 2 + prepare-sources/lib/manifest-types.ts | 39 + prepare-sources/lib/modules.ts | 3 +- .../lib/modules/generate-manifests/README.md | 204 ++++ .../backstage-json-no-version-error/error | 1 + .../input/overlay/source.json | 6 + .../input/workspace/backstage.json | 3 + .../input/workspace/package.json | 8 + .../workspace/plugins/my-plugin/package.json | 7 + .../input/overlay/source.json | 6 + .../input/workspace/package.json | 8 + .../output/workspace/manifest.json | 15 + .../output/workspace/package.json | 8 + .../missing-yarn-lock-error/error | 1 + .../input/overlay/source.json | 6 + .../input/workspace/backstage.json | 3 + .../input/workspace/package.json | 8 + .../workspace/plugins/my-plugin/package.json | 7 + .../input/overlay/source.json | 6 + .../input/workspace/package.json | 8 + .../plugins/plugin-alpha/package.json | 26 + .../plugins/plugin-beta/package.json | 8 + .../output/workspace/manifest.json | 47 + .../output/workspace/package.json | 8 + .../plugins/plugin-alpha/package.json | 26 + .../plugins/plugin-beta/package.json | 8 + .../input/overlay/source.json | 6 + .../input/workspace/backstage.json | 3 + .../input/workspace/package.json | 8 + .../workspace/plugins/my-plugin/package.json | 8 + .../input/workspace/yarn.lock | 33 + .../output/workspace/backstage-manifest.json | 34 + .../output/workspace/backstage.json | 3 + .../output/workspace/manifest.json | 18 + .../output/workspace/package.json | 8 + .../workspace/plugins/my-plugin/package.json | 8 + .../output/workspace/yarn.lock | 33 + .../remote-backstage-manifest.json | 8 + .../no-backstage-json-error/error | 1 + .../input/overlay/source.json | 6 + .../input/workspace/package.json | 8 + .../workspace/plugins/my-plugin/package.json | 7 + .../__fixtures__/version-mismatch-error/error | 1 + .../input/overlay/source.json | 6 + .../input/workspace/backstage.json | 3 + .../input/workspace/package.json | 8 + .../workspace/plugins/my-plugin/package.json | 7 + .../input/workspace/yarn.lock | 8 + .../remote-backstage-manifest.json | 3 + .../modules/generate-manifests/index.test.ts | 364 +++++++ .../lib/modules/generate-manifests/index.ts | 365 +++++++ prepare-sources/lib/test-utils.ts | 71 +- prepare-sources/lib/yarn-lock-parser.test.ts | 953 ++++++++++++++++++ prepare-sources/lib/yarn-lock-parser.ts | 392 +++++++ 54 files changed, 2843 insertions(+), 2 deletions(-) create mode 100644 prepare-sources/lib/manifest-types.ts create mode 100644 prepare-sources/lib/modules/generate-manifests/README.md create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/error create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/backstage.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/plugins/my-plugin/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/error create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/backstage.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/plugins/my-plugin/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/plugins/plugin-alpha/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/plugins/plugin-beta/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/plugins/plugin-alpha/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/plugins/plugin-beta/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/backstage.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/plugins/my-plugin/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/backstage-manifest.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/backstage.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/plugins/my-plugin/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/remote-backstage-manifest.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/error create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/workspace/plugins/my-plugin/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/error create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/backstage.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/plugins/my-plugin/package.json create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/remote-backstage-manifest.json create mode 100644 prepare-sources/lib/modules/generate-manifests/index.test.ts create mode 100644 prepare-sources/lib/modules/generate-manifests/index.ts create mode 100644 prepare-sources/lib/yarn-lock-parser.test.ts create mode 100644 prepare-sources/lib/yarn-lock-parser.ts diff --git a/.sonarcloud.properties b/.sonarcloud.properties index b832489..604b9ef 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -1,2 +1,4 @@ # Test fixtures are not production code; skip analysis. sonar.exclusions=prepare-sources/**/__fixtures__/**/* +# Code duplication detection usually doesn't make sense in test files. +sonar.cpd.exclusions=prepare-sources/lib/**/*.test.ts diff --git a/prepare-sources/lib/manifest-types.ts b/prepare-sources/lib/manifest-types.ts new file mode 100644 index 0000000..809288c --- /dev/null +++ b/prepare-sources/lib/manifest-types.ts @@ -0,0 +1,39 @@ +/** + * Shape of `manifest.json` — inventory of all workspace packages. + * Written by `generate-manifests`, consumed by `protocol-resolution`. + */ +export type WorkspaceManifest = { + packages: WorkspacePackageEntry[]; +}; + +export type WorkspacePackageEntry = { + name: string; + version: string; + path?: string; + dependencies?: Record; + peerDependencies?: Record; + peerDependenciesMeta?: Record>; + optionalDependencies?: Record; + devDependencies?: Record; + bin?: Record; +}; + +/** + * Shape of `backstage-manifest.json` — Backstage release packages with + * dependency metadata. Written by `generate-manifests` (only when the + * workspace has `backstage:^` deps), consumed by `protocol-resolution`. + */ +export type BackstageManifest = { + backstageVersion: string; + packages: BackstagePackageEntry[]; +}; + +export type BackstagePackageEntry = { + name: string; + version: string; + dependencies?: Record; + peerDependencies?: Record; + peerDependenciesMeta?: Record>; + optionalDependencies?: Record; + bin?: Record; +}; diff --git a/prepare-sources/lib/modules.ts b/prepare-sources/lib/modules.ts index 445011d..d3e627a 100644 --- a/prepare-sources/lib/modules.ts +++ b/prepare-sources/lib/modules.ts @@ -1,6 +1,7 @@ import type { ModuleContext, PipelineModule } from "./pipeline.ts"; import { run as hermeticPrep } from "./modules/hermetic-prep/index.ts"; import { run as makeSelfContained } from "./modules/make-self-contained/index.ts"; +import { run as generateManifests } from "./modules/generate-manifests/index.ts"; async function notImplemented(ctx: ModuleContext): Promise { ctx.log("not yet implemented"); @@ -10,7 +11,7 @@ async function notImplemented(ctx: ModuleContext): Promise { export const MODULES: readonly PipelineModule[] = [ { name: "seed-frontend-lockfiles", run: notImplemented }, { name: "make-self-contained", run: makeSelfContained }, - { name: "generate-manifests", run: notImplemented }, + { name: "generate-manifests", run: generateManifests }, { name: "plugin-removal", run: notImplemented }, { name: "file-cleanup", run: notImplemented }, { name: "protocol-resolution", run: notImplemented }, diff --git a/prepare-sources/lib/modules/generate-manifests/README.md b/prepare-sources/lib/modules/generate-manifests/README.md new file mode 100644 index 0000000..6f666be --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/README.md @@ -0,0 +1,204 @@ +# generate-manifests + +Generates package inventories consumed by `protocol-resolution` to resolve +`workspace:^` and `backstage:^` references to concrete npm semver ranges. + +**Pipeline position:** after `make-self-contained`, before `plugin-removal` — +see `modules.ts` for the current ordering. + +**Shared types:** `WorkspaceManifest`, `BackstageManifest`, and their entry +types live in `lib/manifest-types.ts`. Both this module and +`protocol-resolution` depend on those types. + +## Problem + +The `protocol-resolution` module needs to rewrite `workspace:^` and +`backstage:^` protocol references in `package.json` and `yarn.lock`. To do +this, it needs a lookup table mapping package names to their concrete versions +and dependency metadata. + +This information must be captured **before scrubbing** (`plugin-removal`), +because scrubbed packages are removed from disk but their versions are still +needed for protocol resolution — surviving packages may depend on scrubbed +ones via `workspace:^`. + +## What the module produces + +### `manifest.json` + +Inventory of all local workspace packages. Always generated. + +```json +{ + "packages": [ + { + "name": "@scope/plugin-foo", + "version": "1.2.3", + "path": "plugins/plugin-foo/package.json", + "dependencies": { "@scope/plugin-bar": "workspace:^" }, + "peerDependencies": { "react": "^18.0.0" }, + "peerDependenciesMeta": { "react": { "optional": true } }, + "optionalDependencies": { "@emotion/react": "^11.0.0" }, + "devDependencies": { "@types/react": "^18.0.0" }, + "bin": { "foo": "./dist/cli.js" } + } + ] +} +``` + +All dependency fields are optional — only included when non-empty. + +**Package discovery:** Packages are discovered via the `workspaces` field in +the root `package.json` (glob resolution), plus the root package itself. For +flat repos (no `workspaces` field), only the root package is included. + +**Filtering:** Glob matches whose path segments include any of `node_modules`, +`dist-dynamic`, `dist-scalprum`, `dist`, or `build` are excluded. This +prevents build output directories from polluting the manifest. + +**`backstage:^` detection:** The module checks `dependencies`, +`devDependencies`, `peerDependencies`, and `optionalDependencies` across all +packages for `backstage:^` values. If none are found, `backstage-manifest.json` +is skipped entirely. + +### `backstage-manifest.json` + +Backstage release packages with dependency metadata. Only generated when the +workspace has `backstage:^` dependencies. Requires `backstage.json` at the +workspace root (throws if missing). + +```json +{ + "backstageVersion": "1.42.5", + "packages": [ + { + "name": "@backstage/core-plugin-api", + "version": "1.10.9", + "dependencies": { "@backstage/types": "npm:^1.2.3" }, + "peerDependencies": { "react": "npm:^18.0.0" }, + "peerDependenciesMeta": { "react": { "optional": true } }, + "optionalDependencies": { "@emotion/react": "npm:^11.0.0" }, + "bin": { "backstage-core": "./dist/cli.js" } + } + ] +} +``` + +Note that dependency values in the backstage manifest use the Yarn-resolved +format (`npm:^X.Y.Z`), since they come from `yarn.lock` rather than +`package.json`. + +Neither file is included in the OCI artifact — they are build-time +intermediates. + +## Why backstage metadata comes from yarn.lock, not the npm registry + +The original `generate-backstage-manifest.js` in `sync-midstream.sh` fetched +the Backstage release manifest from `versions.backstage.io` (one HTTP call), +then enriched each of the ~600 packages with dependency metadata from +`registry.npmjs.org` (60+ batched HTTP calls). The result was cached to disk +by Backstage version to amortize the cost across workspaces. + +This module takes a different approach: it **extracts backstage package +metadata directly from the workspace's `yarn.lock`**, using the shared +`yarn-lock-parser` (`lib/yarn-lock-parser.ts`). + +### Rationale + +After `yarn install --immutable` (which runs before this module), the +`yarn.lock` already contains the resolved version and full dependency metadata +for every `@backstage/*` package. These entries were created by the Backstage +Yarn plugin, which resolves `backstage:^` by looking up the exact version from +`versions.backstage.io` at install time. So the lockfile is a local cache of +the canonical version mapping, enriched with the dependency metadata that npm +registry calls would have provided. + +**Benefits:** + +- **Zero npm registry calls.** The original script made hundreds of HTTP + requests. This module reads local files only (plus one validation fetch). +- **No caching needed.** The original script cached results to `/tmp/` to + avoid redundant fetches across workspaces in the same `sync-midstream.sh` + run. In the new per-workspace CI model (separate workflow run per + workspace), there's no shared filesystem to cache to. Since we read from the + lockfile, there's nothing to cache. +- **More accurate.** The lockfile reflects what was actually resolved for this + specific workspace, not a generic npm registry response. + +**Validation:** The module fetches the Backstage release manifest from +`versions.backstage.io` (a single HTTP call) and compares each extracted +version against the canonical manifest. A mismatch throws — indicating a stale +lockfile or unexpected inconsistency. This is a defensive check; by +construction, `yarn install --immutable` guarantees the lockfile is consistent +with the Backstage Yarn plugin's resolution. + +### Why the versions are guaranteed to match + +The `backstage:^` protocol is resolved by the Backstage Yarn plugin, which: + +1. Reads `backstage.json` to get the target release version +2. Fetches `versions.backstage.io/v1/releases//manifest.json` +3. Resolves each `backstage:^` to the exact version from that manifest +4. Writes the result to `yarn.lock` + +After `yarn install --immutable`, the lockfile entries for `backstage:^` are +by construction the same versions as the canonical manifest. The validation +fetch is belt-and-suspenders — it catches corruption, plugin bugs, or manual +lockfile edits that should never happen in CI. + +## Why upstream fetching is no longer needed + +The original `generate-workspace-manifest.js` fetched versions from GitHub for +packages that didn't exist locally — these were packages referenced by +`workspace:^` but deleted by scrubbing before the manifest was generated. The +manifest tagged these entries with `path: 'upstream'` and `source: 'upstream'` +so that downstream consumers (`createTypeShimsPackage` in `update-workspace.js`) +could distinguish them from packages that were once local. + +In the new pipeline, this entire mechanism is unnecessary because manifest +generation runs **before** `plugin-removal`. All workspace packages are still +on disk, so every entry in the manifest has a real `path`. When +`protocol-resolution` later needs to distinguish surviving from scrubbed +packages, it simply checks `fs.existsSync(dirname(pkg.path))` — exactly as the +old `update-workspace.js` already does (lines 1722, 1736, 1799). The +`path === 'upstream'` marker is never needed. + +## Differences from sync-midstream.sh + +| Aspect | Original (sync-midstream.sh) | New (this module) | +| ------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | +| Upstream version fetching | Fetches missing `workspace:` deps from GitHub raw URLs | Not needed — all packages are local (runs before scrubbing) | +| Backstage metadata source | `versions.backstage.io` + npm registry (~600 HTTP calls) | `yarn.lock` extraction + one validation fetch | +| Caching | `/tmp/backstage-manifest-cache/` (shared across workspaces) | None needed | +| Error handling | Swallowed (`\|\| true`, stderr discarded) | Throws on error (pipeline aborts) | +| Package discovery | Recursive scan with skip-list heuristics | `workspaces` field glob resolution + filter | +| `bin` normalization | String → object (same) | String → object (same) | +| yarn.lock parsing | N/A (backstage manifest came from npm) | Shared `yarn-lock-parser` (`lib/yarn-lock-parser.ts`) | + +## Log messages + +Log messages are aligned with the original scripts for familiarity: + +| Log | When | +| ------------------------------------------------- | --------------------------------- | +| `Scanning for package.json files...` | Always (start of module) | +| `Found N local packages` | Always | +| ` - @scope/pkg@1.2.3` | Per package | +| `Manifest written to: manifest.json` | Always | +| `No backstage:^ dependencies found, skipping` | No `backstage:^` in any dep field | +| `Backstage version: X.Y.Z` | Backstage manifest path | +| `Extracted N @backstage/* entries from yarn.lock` | After lockfile parsing | +| `Validating against ` | Before validation fetch | +| `All N entries validated against Backstage X.Y.Z` | After successful validation | +| `Written: backstage-manifest.json (N packages)` | Backstage manifest written | + +## Error conditions + +| Condition | Behavior | +| ---------------------------------------------------------------- | ------------------------------------------- | +| No `backstage:^` deps in any `package.json` | Skip — no `backstage-manifest.json` written | +| Has `backstage:^` deps but no `backstage.json` | Throw | +| `backstage.json` exists but has no `version` field | Throw | +| `yarn.lock` missing (when backstage manifest needed) | Throw | +| Version mismatch between `yarn.lock` and `versions.backstage.io` | Throw with details | +| Failed to fetch `versions.backstage.io` | Throw with HTTP status | diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/error b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/error new file mode 100644 index 0000000..97f6ca6 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/error @@ -0,0 +1 @@ +/no 'version' field/ \ No newline at end of file diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/overlay/source.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/backstage.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/backstage.json new file mode 100644 index 0000000..4df5066 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/backstage.json @@ -0,0 +1,3 @@ +{ + "description": "backstage.json without a version field" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/package.json new file mode 100644 index 0000000..0136fd8 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/workspace-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/plugins/my-plugin/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/plugins/my-plugin/package.json new file mode 100644 index 0000000..c47611b --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/backstage-json-no-version-error/input/workspace/plugins/my-plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/my-plugin", + "version": "1.0.0", + "dependencies": { + "@backstage/core-plugin-api": "backstage:^" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/input/overlay/source.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/input/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/input/workspace/package.json new file mode 100644 index 0000000..6da0c9e --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/standalone-plugin", + "version": "3.0.1", + "bin": "./dist/cli.js", + "dependencies": { + "express": "^4.18.0" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/output/workspace/manifest.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/output/workspace/manifest.json new file mode 100644 index 0000000..e54c2d3 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/output/workspace/manifest.json @@ -0,0 +1,15 @@ +{ + "packages": [ + { + "name": "@test/standalone-plugin", + "version": "3.0.1", + "path": "package.json", + "dependencies": { + "express": "^4.18.0" + }, + "bin": { + "standalone-plugin": "./dist/cli.js" + } + } + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/output/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/output/workspace/package.json new file mode 100644 index 0000000..6da0c9e --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/flat-repo-single-package/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/standalone-plugin", + "version": "3.0.1", + "bin": "./dist/cli.js", + "dependencies": { + "express": "^4.18.0" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/error b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/error new file mode 100644 index 0000000..1eab240 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/error @@ -0,0 +1 @@ +/yarn\.lock not found/ \ No newline at end of file diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/overlay/source.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/backstage.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/backstage.json new file mode 100644 index 0000000..6c12971 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/backstage.json @@ -0,0 +1,3 @@ +{ + "version": "1.42.5" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/package.json new file mode 100644 index 0000000..0136fd8 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/workspace-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/plugins/my-plugin/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/plugins/my-plugin/package.json new file mode 100644 index 0000000..c47611b --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/missing-yarn-lock-error/input/workspace/plugins/my-plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/my-plugin", + "version": "1.0.0", + "dependencies": { + "@backstage/core-plugin-api": "backstage:^" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/overlay/source.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/package.json new file mode 100644 index 0000000..0136fd8 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/workspace-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/plugins/plugin-alpha/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/plugins/plugin-alpha/package.json new file mode 100644 index 0000000..fb49c94 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/plugins/plugin-alpha/package.json @@ -0,0 +1,26 @@ +{ + "name": "@test/plugin-alpha", + "version": "2.1.0", + "bin": { + "alpha-tool": "./dist/cli.js" + }, + "dependencies": { + "@test/plugin-beta": "workspace:^", + "react": "^18.0.0" + }, + "devDependencies": { + "@types/react": "^18.0.0", + "typescript": "~5.3.0" + }, + "peerDependencies": { + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + }, + "optionalDependencies": { + "fsevents": "^2.3.0" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/plugins/plugin-beta/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/plugins/plugin-beta/package.json new file mode 100644 index 0000000..518a25d --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/input/workspace/plugins/plugin-beta/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/plugin-beta", + "version": "1.3.0", + "bin": "./dist/index.js", + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/manifest.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/manifest.json new file mode 100644 index 0000000..7ec5cfe --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/manifest.json @@ -0,0 +1,47 @@ +{ + "packages": [ + { + "name": "@test/plugin-alpha", + "version": "2.1.0", + "path": "plugins/plugin-alpha/package.json", + "dependencies": { + "@test/plugin-beta": "workspace:^", + "react": "^18.0.0" + }, + "peerDependencies": { + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + }, + "optionalDependencies": { + "fsevents": "^2.3.0" + }, + "devDependencies": { + "@types/react": "^18.0.0", + "typescript": "~5.3.0" + }, + "bin": { + "alpha-tool": "./dist/cli.js" + } + }, + { + "name": "@test/plugin-beta", + "version": "1.3.0", + "path": "plugins/plugin-beta/package.json", + "dependencies": { + "lodash": "^4.17.21" + }, + "bin": { + "plugin-beta": "./dist/index.js" + } + }, + { + "name": "@test/workspace-root", + "version": "1.0.0", + "path": "package.json" + } + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/package.json new file mode 100644 index 0000000..0136fd8 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/workspace-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/plugins/plugin-alpha/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/plugins/plugin-alpha/package.json new file mode 100644 index 0000000..fb49c94 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/plugins/plugin-alpha/package.json @@ -0,0 +1,26 @@ +{ + "name": "@test/plugin-alpha", + "version": "2.1.0", + "bin": { + "alpha-tool": "./dist/cli.js" + }, + "dependencies": { + "@test/plugin-beta": "workspace:^", + "react": "^18.0.0" + }, + "devDependencies": { + "@types/react": "^18.0.0", + "typescript": "~5.3.0" + }, + "peerDependencies": { + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + }, + "optionalDependencies": { + "fsevents": "^2.3.0" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/plugins/plugin-beta/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/plugins/plugin-beta/package.json new file mode 100644 index 0000000..518a25d --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-no-backstage/output/workspace/plugins/plugin-beta/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/plugin-beta", + "version": "1.3.0", + "bin": "./dist/index.js", + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/overlay/source.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/backstage.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/backstage.json new file mode 100644 index 0000000..6c12971 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/backstage.json @@ -0,0 +1,3 @@ +{ + "version": "1.42.5" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/package.json new file mode 100644 index 0000000..0136fd8 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/workspace-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/plugins/my-plugin/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/plugins/my-plugin/package.json new file mode 100644 index 0000000..a8becc3 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/plugins/my-plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/my-plugin", + "version": "1.5.0", + "dependencies": { + "@backstage/core-plugin-api": "backstage:^", + "@backstage/theme": "backstage:^" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/yarn.lock b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/yarn.lock new file mode 100644 index 0000000..ce2da80 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/yarn.lock @@ -0,0 +1,33 @@ +__metadata: + version: 8 + cacheKey: 10c0 + +"@backstage/core-plugin-api@backstage:^": + version: 1.10.9 + resolution: "@backstage/core-plugin-api@npm:1.10.9" + dependencies: + "@backstage/types": "npm:^1.2.3" + react: "npm:^18.0.0" + peerDependencies: + react: "npm:^18.0.0" + bin: + backstage-core: ./dist/cli.js + checksum: abc123 + +"@backstage/theme@backstage:^": + version: 0.6.3 + resolution: "@backstage/theme@npm:0.6.3" + optionalDependencies: + "@emotion/react": "npm:^11.0.0" + peerDependencies: + react: "npm:^18.0.0" + peerDependenciesMeta: + react: + optional: true + checksum: def456 + +"@test/workspace-root@workspace:.": + version: 0.0.0-use.local + resolution: "@test/workspace-root@workspace:." + languageName: unknown + linkType: soft diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/backstage-manifest.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/backstage-manifest.json new file mode 100644 index 0000000..ca63d43 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/backstage-manifest.json @@ -0,0 +1,34 @@ +{ + "backstageVersion": "1.42.5", + "packages": [ + { + "name": "@backstage/core-plugin-api", + "version": "1.10.9", + "dependencies": { + "@backstage/types": "npm:^1.2.3", + "react": "npm:^18.0.0" + }, + "peerDependencies": { + "react": "npm:^18.0.0" + }, + "bin": { + "backstage-core": "./dist/cli.js" + } + }, + { + "name": "@backstage/theme", + "version": "0.6.3", + "peerDependencies": { + "react": "npm:^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + }, + "optionalDependencies": { + "@emotion/react": "npm:^11.0.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/backstage.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/backstage.json new file mode 100644 index 0000000..6c12971 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/backstage.json @@ -0,0 +1,3 @@ +{ + "version": "1.42.5" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/manifest.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/manifest.json new file mode 100644 index 0000000..9f42332 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/manifest.json @@ -0,0 +1,18 @@ +{ + "packages": [ + { + "name": "@test/my-plugin", + "version": "1.5.0", + "path": "plugins/my-plugin/package.json", + "dependencies": { + "@backstage/core-plugin-api": "backstage:^", + "@backstage/theme": "backstage:^" + } + }, + { + "name": "@test/workspace-root", + "version": "1.0.0", + "path": "package.json" + } + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/package.json new file mode 100644 index 0000000..0136fd8 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/workspace-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/plugins/my-plugin/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/plugins/my-plugin/package.json new file mode 100644 index 0000000..a8becc3 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/plugins/my-plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/my-plugin", + "version": "1.5.0", + "dependencies": { + "@backstage/core-plugin-api": "backstage:^", + "@backstage/theme": "backstage:^" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/yarn.lock b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/yarn.lock new file mode 100644 index 0000000..ce2da80 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/output/workspace/yarn.lock @@ -0,0 +1,33 @@ +__metadata: + version: 8 + cacheKey: 10c0 + +"@backstage/core-plugin-api@backstage:^": + version: 1.10.9 + resolution: "@backstage/core-plugin-api@npm:1.10.9" + dependencies: + "@backstage/types": "npm:^1.2.3" + react: "npm:^18.0.0" + peerDependencies: + react: "npm:^18.0.0" + bin: + backstage-core: ./dist/cli.js + checksum: abc123 + +"@backstage/theme@backstage:^": + version: 0.6.3 + resolution: "@backstage/theme@npm:0.6.3" + optionalDependencies: + "@emotion/react": "npm:^11.0.0" + peerDependencies: + react: "npm:^18.0.0" + peerDependenciesMeta: + react: + optional: true + checksum: def456 + +"@test/workspace-root@workspace:.": + version: 0.0.0-use.local + resolution: "@test/workspace-root@workspace:." + languageName: unknown + linkType: soft diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/remote-backstage-manifest.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/remote-backstage-manifest.json new file mode 100644 index 0000000..47d329b --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/monorepo-with-backstage/remote-backstage-manifest.json @@ -0,0 +1,8 @@ +{ + "packages": [ + { "name": "@backstage/core-plugin-api", "version": "1.10.9" }, + { "name": "@backstage/theme", "version": "0.6.3" }, + { "name": "@backstage/types", "version": "1.2.3" }, + { "name": "@backstage/catalog-model", "version": "1.8.1" } + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/error b/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/error new file mode 100644 index 0000000..50fb61e --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/error @@ -0,0 +1 @@ +/backstage:.*dependencies but no backstage\.json/ \ No newline at end of file diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/overlay/source.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/workspace/package.json new file mode 100644 index 0000000..0136fd8 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/workspace-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/workspace/plugins/my-plugin/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/workspace/plugins/my-plugin/package.json new file mode 100644 index 0000000..c47611b --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/no-backstage-json-error/input/workspace/plugins/my-plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/my-plugin", + "version": "1.0.0", + "dependencies": { + "@backstage/core-plugin-api": "backstage:^" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/error b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/error new file mode 100644 index 0000000..4bd5b61 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/error @@ -0,0 +1 @@ +/backstage version mismatch/ \ No newline at end of file diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/overlay/source.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/backstage.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/backstage.json new file mode 100644 index 0000000..6c12971 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/backstage.json @@ -0,0 +1,3 @@ +{ + "version": "1.42.5" +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/package.json new file mode 100644 index 0000000..0136fd8 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/workspace-root", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/plugins/my-plugin/package.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/plugins/my-plugin/package.json new file mode 100644 index 0000000..c47611b --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/plugins/my-plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/my-plugin", + "version": "1.0.0", + "dependencies": { + "@backstage/core-plugin-api": "backstage:^" + } +} diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/yarn.lock b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/yarn.lock new file mode 100644 index 0000000..01f9cf3 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/input/workspace/yarn.lock @@ -0,0 +1,8 @@ +__metadata: + version: 8 + cacheKey: 10c0 + +"@backstage/core-plugin-api@backstage:^": + version: 1.10.8 + resolution: "@backstage/core-plugin-api@npm:1.10.8" + checksum: stale123 diff --git a/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/remote-backstage-manifest.json b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/remote-backstage-manifest.json new file mode 100644 index 0000000..cf77e4e --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/__fixtures__/version-mismatch-error/remote-backstage-manifest.json @@ -0,0 +1,3 @@ +{ + "packages": [{ "name": "@backstage/core-plugin-api", "version": "1.10.9" }] +} diff --git a/prepare-sources/lib/modules/generate-manifests/index.test.ts b/prepare-sources/lib/modules/generate-manifests/index.test.ts new file mode 100644 index 0000000..6d7b5d9 --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/index.test.ts @@ -0,0 +1,364 @@ +import fs from "node:fs"; +import path from "node:path"; +import { afterEach, describe, expect, it, vi } from "vite-plus/test"; + +import { + loadFixture, + mockFetch, + type MockFetchResponse, + testInputOutputExpectations, +} from "../../test-utils.ts"; +import { + run, + extractBackstageEntries, + extractPackageInfo, + findWorkspacePackageJsonFiles, + getBackstageVersion, + normalizeBin, +} from "./index.ts"; + +afterEach(() => { + vi.restoreAllMocks(); +}); + +describe("generate-manifests", () => { + testInputOutputExpectations(import.meta.dirname, run, { + setup: (fixture, fixtureDir) => { + const releaseFile = path.join(fixtureDir, "remote-backstage-manifest.json"); + if (!fs.existsSync(releaseFile)) return; + + const backstageJsonPath = path.join(fixture.ctx.workspacePath, "backstage.json"); + if (!fs.existsSync(backstageJsonPath)) return; + + const version = JSON.parse(fs.readFileSync(backstageJsonPath, "utf8")).version; + const responseBody = JSON.parse(fs.readFileSync(releaseFile, "utf8")); + mockFetch({ + [`https://versions.backstage.io/v1/releases/${version}/manifest.json`]: responseBody, + }); + }, + }); + + it("logs package counts for workspace with backstage deps", async () => { + using fixture = loadFixture(import.meta.dirname, "monorepo-with-backstage"); + const releaseFile = path.join( + import.meta.dirname, + "__fixtures__/monorepo-with-backstage/remote-backstage-manifest.json", + ); + const version = "1.42.5"; + mockFetch({ + [`https://versions.backstage.io/v1/releases/${version}/manifest.json`]: JSON.parse( + fs.readFileSync(releaseFile, "utf8"), + ), + }); + await run(fixture.ctx); + expect(fixture.ctx.log).toHaveBeenCalledWith(expect.stringContaining("Found")); + expect(fixture.ctx.log).toHaveBeenCalledWith(expect.stringContaining("Manifest written to:")); + expect(fixture.ctx.log).toHaveBeenCalledWith( + expect.stringContaining("Written: backstage-manifest.json"), + ); + }); + + it("throws when versions.backstage.io returns HTTP error", async () => { + using fixture = loadFixture(import.meta.dirname, "monorepo-with-backstage"); + const version = "1.42.5"; + mockFetch({ + [`https://versions.backstage.io/v1/releases/${version}/manifest.json`]: { + body: null, + status: 503, + ok: false, + } satisfies MockFetchResponse, + }); + await expect(run(fixture.ctx)).rejects.toThrow(/HTTP 503/); + }); + + it("throws when manifest response has no packages array", async () => { + using fixture = loadFixture(import.meta.dirname, "monorepo-with-backstage"); + const version = "1.42.5"; + mockFetch({ + [`https://versions.backstage.io/v1/releases/${version}/manifest.json`]: { + releaseVersion: version, + }, + }); + await expect(run(fixture.ctx)).rejects.toThrow(/invalid Backstage manifest response/); + }); + + it("skips malformed entries in manifest packages array", async () => { + using fixture = loadFixture(import.meta.dirname, "monorepo-with-backstage"); + const version = "1.42.5"; + mockFetch({ + [`https://versions.backstage.io/v1/releases/${version}/manifest.json`]: { + packages: [ + null, + 42, + { name: "@backstage/core-plugin-api", version: "1.10.9" }, + { name: "@backstage/theme", version: "0.6.3" }, + { name: "@backstage/types", version: "1.2.3" }, + { name: "@backstage/catalog-model", version: "1.8.1" }, + { noVersion: true }, + { name: 123, version: "1.0.0" }, + ], + }, + }); + await run(fixture.ctx); + expect(fixture.ctx.log).toHaveBeenCalledWith(expect.stringContaining("Found")); + }); +}); + +// --------------------------------------------------------------------------- +// Unit tests for extractBackstageEntries +// --------------------------------------------------------------------------- + +describe("extractBackstageEntries", () => { + it("extracts all field types from a complete lockfile", () => { + const lockContent = ` +"react@npm:^18.0.0": + version: 18.3.1 + resolution: "react@npm:18.3.1" + checksum: def + +"@backstage/core-plugin-api@backstage:^": + version: 1.10.9 + resolution: "@backstage/core-plugin-api@npm:1.10.9" + dependencies: + "@backstage/types": "npm:^1.2.3" + bin: + backstage-cli: ./bin/backstage-cli + checksum: abc123 + +"@backstage/theme@backstage:^": + version: 0.6.3 + resolution: "@backstage/theme@npm:0.6.3" + peerDependencies: + react: "npm:^18.0.0" + peerDependenciesMeta: + react: + optional: true + @emotion/react: + reason: styling + optional: false + optionalDependencies: + "@emotion/react": "npm:^11.0.0" + checksum: xyz789 +`; + const entries = extractBackstageEntries(lockContent); + expect(entries).toHaveLength(2); + + expect(entries[0]).toEqual({ + name: "@backstage/core-plugin-api", + version: "1.10.9", + dependencies: { "@backstage/types": "npm:^1.2.3" }, + bin: { "backstage-cli": "./bin/backstage-cli" }, + }); + + expect(entries[1]).toEqual({ + name: "@backstage/theme", + version: "0.6.3", + peerDependencies: { react: "npm:^18.0.0" }, + peerDependenciesMeta: { + react: { optional: true }, + "@emotion/react": { reason: "styling", optional: false }, + }, + optionalDependencies: { "@emotion/react": "npm:^11.0.0" }, + }); + }); + + it("skips entries with malformed descriptor, missing version, or no backstage deps", () => { + const lockContent = ` +"react@npm:^18.0.0": + version: 18.3.1 + checksum: def + +"backstage:^": + version: 1.0.0 + resolution: "something@npm:1.0.0" + checksum: abc + +"@backstage/core-plugin-api@backstage:^": + resolution: "@backstage/core-plugin-api@npm:1.10.9" + checksum: abc +`; + expect(extractBackstageEntries(lockContent)).toEqual([]); + }); + + it("omits empty dependency and peerDependenciesMeta sections", () => { + const lockContent = ` +"@backstage/core-plugin-api@backstage:^": + version: 1.10.9 + resolution: "@backstage/core-plugin-api@npm:1.10.9" + dependencies: + peerDependenciesMeta: + checksum: abc +`; + const entries = extractBackstageEntries(lockContent); + expect(entries).toHaveLength(1); + const entry = entries[0]; + expect(entry).toBeDefined(); + expect(entry?.dependencies).toBeUndefined(); + expect(entry?.peerDependenciesMeta).toBeUndefined(); + }); + + it("omits dependency fields when all map entries are malformed", () => { + const lockContent = [ + '"@backstage/core-plugin-api@backstage:^":', + " version: 1.10.9", + ' resolution: "@backstage/core-plugin-api@npm:1.10.9"', + " dependencies:", + " no-colon-garbage", + " also-no-colon-garbage", + " checksum: abc", + ].join("\n"); + const entries = extractBackstageEntries(lockContent); + expect(entries).toHaveLength(1); + const entry = entries[0]; + expect(entry).toBeDefined(); + expect(entry?.dependencies).toBeUndefined(); + }); + + it("omits peerDependenciesMeta when all nested-map keys are malformed", () => { + const lockContent = [ + '"@backstage/core-plugin-api@backstage:^":', + " version: 1.10.9", + ' resolution: "@backstage/core-plugin-api@npm:1.10.9"', + " peerDependenciesMeta:", + " not-a-key-header 1.0.0", + " orphan-prop: true", + " checksum: abc", + ].join("\n"); + const entries = extractBackstageEntries(lockContent); + expect(entries).toHaveLength(1); + const entry = entries[0]; + expect(entry).toBeDefined(); + expect(entry?.peerDependenciesMeta).toBeUndefined(); + }); + + it("handles malformed lockfile content gracefully", () => { + const lockContent = [ + '"@backstage/core-plugin-api@backstage:^":', + " version: 1.10.9", + ' resolution: "@backstage/core-plugin-api@npm:1.10.9"', + " dependencies:", + " !!!not-a-valid-line!!!", + ' "@backstage/types": "npm:^1.2.3"', + " peerDependenciesMeta:", + " orphan-field: true", + " react:", + " optional: true", + " ", + " checksum: abc", + ].join("\n"); + const entries = extractBackstageEntries(lockContent); + expect(entries).toHaveLength(1); + const entry = entries[0]; + expect(entry).toBeDefined(); + expect(entry?.dependencies).toEqual({ "@backstage/types": "npm:^1.2.3" }); + expect(entry?.peerDependenciesMeta).toEqual({ react: { optional: true } }); + }); +}); + +// --------------------------------------------------------------------------- +// Unit tests for normalizeBin +// --------------------------------------------------------------------------- + +describe("normalizeBin", () => { + const cases: Array< + [string, string, string | Record, Record | undefined] + > = [ + ["scoped string → object", "@scope/my-cli", "./dist/cli.js", { "my-cli": "./dist/cli.js" }], + ["unscoped string → object", "my-tool", "./cli.js", { "my-tool": "./cli.js" }], + [ + "object passthrough", + "@scope/pkg", + { "tool-a": "./a.js", "tool-b": "./b.js" }, + { "tool-a": "./a.js", "tool-b": "./b.js" }, + ], + ["empty object → undefined", "@scope/pkg", {}, undefined], + ]; + + it.each(cases)("%s", (_label, name, bin, expected) => { + expect(normalizeBin(name, bin)).toEqual(expected); + }); +}); + +// --------------------------------------------------------------------------- +// Unit tests for findWorkspacePackageJsonFiles +// --------------------------------------------------------------------------- + +describe("findWorkspacePackageJsonFiles", () => { + it("finds root package.json for flat repo (no workspaces field)", () => { + using fixture = loadFixture(import.meta.dirname, "flat-repo-single-package"); + const files = findWorkspacePackageJsonFiles(fixture.ctx.workspacePath); + expect(files).toHaveLength(1); + expect(files[0]).toContain("package.json"); + }); + + it("finds root + workspace members for monorepo", () => { + using fixture = loadFixture(import.meta.dirname, "monorepo-no-backstage"); + const files = findWorkspacePackageJsonFiles(fixture.ctx.workspacePath); + expect(files).toHaveLength(3); + }); + + it("handles edge cases: missing root, dist-dynamic exclusion, empty glob match", () => { + using fixture = loadFixture(import.meta.dirname, "monorepo-no-backstage"); + const wp = fixture.ctx.workspacePath; + + fs.mkdirSync(path.join(wp, "plugins", "empty-dir"), { recursive: true }); + expect(findWorkspacePackageJsonFiles(wp)).toHaveLength(3); + + const distDir = path.join(wp, "plugins", "dist-dynamic"); + fs.mkdirSync(distDir, { recursive: true }); + fs.writeFileSync( + path.join(distDir, "package.json"), + JSON.stringify({ name: "should-be-excluded", version: "0.0.0" }), + ); + expect(findWorkspacePackageJsonFiles(wp)).toHaveLength(3); + expect(findWorkspacePackageJsonFiles(wp).every((f) => !f.includes("dist-dynamic"))).toBe(true); + + fs.unlinkSync(path.join(wp, "package.json")); + expect(findWorkspacePackageJsonFiles(wp)).toEqual([]); + }); +}); + +// --------------------------------------------------------------------------- +// Unit tests for getBackstageVersion +// --------------------------------------------------------------------------- + +describe("getBackstageVersion", () => { + it("reads version from backstage.json", () => { + using fixture = loadFixture(import.meta.dirname, "monorepo-with-backstage"); + expect(getBackstageVersion(fixture.ctx.workspacePath)).toBe("1.42.5"); + }); + + it("throws when backstage.json is missing", () => { + using fixture = loadFixture(import.meta.dirname, "monorepo-no-backstage"); + expect(() => getBackstageVersion(fixture.ctx.workspacePath)).toThrow(/no backstage\.json/); + }); +}); + +// --------------------------------------------------------------------------- +// Unit tests for extractPackageInfo +// --------------------------------------------------------------------------- + +describe("extractPackageInfo", () => { + it("returns null for missing name or version, filtering them from manifest", async () => { + using fixture = loadFixture(import.meta.dirname, "monorepo-no-backstage"); + const rootPkgPath = path.join(fixture.ctx.workspacePath, "package.json"); + const content = JSON.parse(fs.readFileSync(rootPkgPath, "utf8")); + + fs.writeFileSync(rootPkgPath, JSON.stringify({ ...content, name: undefined })); + expect(extractPackageInfo(rootPkgPath, fixture.ctx.workspacePath)).toBeNull(); + + fs.writeFileSync(rootPkgPath, JSON.stringify({ ...content, version: undefined })); + expect(extractPackageInfo(rootPkgPath, fixture.ctx.workspacePath)).toBeNull(); + + fs.writeFileSync(rootPkgPath, JSON.stringify(content)); + const alphaPath = path.join( + fixture.ctx.workspacePath, + "plugins", + "plugin-alpha", + "package.json", + ); + fs.writeFileSync(alphaPath, JSON.stringify({ version: "1.0.0" })); + await run(fixture.ctx); + expect(fixture.ctx.log).toHaveBeenCalledWith(expect.stringMatching(/Found 2 local packages/)); + }); +}); diff --git a/prepare-sources/lib/modules/generate-manifests/index.ts b/prepare-sources/lib/modules/generate-manifests/index.ts new file mode 100644 index 0000000..aeda39e --- /dev/null +++ b/prepare-sources/lib/modules/generate-manifests/index.ts @@ -0,0 +1,365 @@ +import fs from "node:fs"; +import path from "node:path"; +import type { ModuleContext } from "../../pipeline.ts"; +import type { + BackstageManifest, + BackstagePackageEntry, + WorkspaceManifest, + WorkspacePackageEntry, +} from "../../manifest-types.ts"; +import { + type LockfileBlock, + getMap, + getNestedMap, + getScalar, + parseLockfile, +} from "../../yarn-lock-parser.ts"; + +const VERSIONS_BACKSTAGE_IO = "https://versions.backstage.io/v1/releases"; + +const EXCLUDE_DIRS = new Set(["node_modules", "dist-dynamic", "dist-scalprum", "dist", "build"]); + +/** + * Generates `manifest.json` (workspace package inventory) and optionally + * `backstage-manifest.json` (Backstage release packages with dependency + * metadata, extracted from `yarn.lock` and validated against + * `versions.backstage.io`). + * + * Must run before scrubbing so that versions of to-be-scrubbed packages are + * captured. Not included in the OCI artifact. + */ +export async function run(ctx: ModuleContext): Promise { + ctx.log("Scanning for package.json files..."); + const workspaceManifest = generateWorkspaceManifest(ctx); + + ctx.log(`Found ${workspaceManifest.packages.length} local packages`); + for (const pkg of workspaceManifest.packages) { + ctx.log(` - ${pkg.name}@${pkg.version}`); + } + + const manifestPath = path.join(ctx.workspacePath, "manifest.json"); + writeJson(manifestPath, workspaceManifest); + ctx.log(`Manifest written to: manifest.json`); + + if (!manifestHasBackstageDeps(workspaceManifest)) { + ctx.log("No backstage:^ dependencies found, skipping"); + return; + } + + const backstageManifest = await generateBackstageManifest(ctx); + const backstagePath = path.join(ctx.workspacePath, "backstage-manifest.json"); + writeJson(backstagePath, backstageManifest); + ctx.log(`Written: backstage-manifest.json (${backstageManifest.packages.length} packages)`); +} + +function manifestHasBackstageDeps(manifest: WorkspaceManifest): boolean { + return manifest.packages.some((pkg) => { + const allDeps = [ + pkg.dependencies, + pkg.devDependencies, + pkg.peerDependencies, + pkg.optionalDependencies, + ]; + return allDeps.some((deps) => deps && Object.values(deps).includes("backstage:^")); + }); +} + +// --------------------------------------------------------------------------- +// Workspace manifest +// --------------------------------------------------------------------------- + +function generateWorkspaceManifest(ctx: ModuleContext): WorkspaceManifest { + const packageJsonPaths = findWorkspacePackageJsonFiles(ctx.workspacePath); + const packages: WorkspacePackageEntry[] = []; + + for (const pkgPath of packageJsonPaths) { + const entry = extractPackageInfo(pkgPath, ctx.workspacePath); + if (entry) packages.push(entry); + } + + packages.sort((a, b) => a.name.localeCompare(b.name)); + return { packages }; +} + +/** + * Discover workspace package.json files using the `workspaces` field from + * the root package.json, filtered to exclude build output directories. + * For flat repos (no `workspaces` field), returns just the root. + */ +export function findWorkspacePackageJsonFiles(workspacePath: string): string[] { + const rootPkgPath = path.join(workspacePath, "package.json"); + if (!fs.existsSync(rootPkgPath)) return []; + + const rootPkg = JSON.parse(fs.readFileSync(rootPkgPath, "utf8")); + const patterns: string[] = rootPkg.workspaces ?? []; + const results = [rootPkgPath]; + + for (const pattern of patterns) { + const matches = fs.globSync(pattern, { cwd: workspacePath }); + for (const match of matches) { + if (match.split(path.sep).some((seg) => EXCLUDE_DIRS.has(seg))) continue; + const pkgPath = path.join(workspacePath, match, "package.json"); + if (fs.existsSync(pkgPath)) results.push(pkgPath); + } + } + + return results; +} + +const DEP_FIELDS = [ + "dependencies", + "peerDependencies", + "peerDependenciesMeta", + "optionalDependencies", + "devDependencies", +] as const; + +export function extractPackageInfo( + packageJsonPath: string, + baseDir: string, +): WorkspacePackageEntry | null { + const content = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")); + if (!content.name || !content.version) return null; + + const entry: WorkspacePackageEntry = { + name: content.name, + version: content.version, + path: path.relative(path.resolve(baseDir), packageJsonPath), + }; + + for (const field of DEP_FIELDS) { + if (content[field] && Object.keys(content[field]).length > 0) { + (entry as Record)[field] = content[field]; + } + } + + if (content.bin) { + entry.bin = normalizeBin(content.name, content.bin); + } + + return entry; +} + +/** + * Normalize the `bin` field to always be an object. + * String form `"./cli.js"` becomes `{ "": "./cli.js" }`. + */ +export function normalizeBin( + packageName: string, + bin: string | Record, +): Record | undefined { + if (typeof bin === "string") { + const slashPos = packageName.lastIndexOf("/"); + const unscopedName = slashPos === -1 ? packageName : packageName.substring(slashPos + 1); + return { [unscopedName]: bin }; + } + if (Object.keys(bin).length > 0) return bin; + return undefined; +} + +// --------------------------------------------------------------------------- +// Backstage manifest +// --------------------------------------------------------------------------- + +async function generateBackstageManifest(ctx: ModuleContext): Promise { + const backstageVersion = getBackstageVersion(ctx.workspacePath); + ctx.log(`Backstage version: ${backstageVersion}`); + + const yarnLockPath = path.join(ctx.workspacePath, "yarn.lock"); + if (!fs.existsSync(yarnLockPath)) { + throw new Error("yarn.lock not found — cannot extract backstage package metadata"); + } + + const lockContent = fs.readFileSync(yarnLockPath, "utf8"); + const entries = extractBackstageEntries(lockContent); + ctx.log(`Extracted ${entries.length} @backstage/* entries from yarn.lock`); + + await validateBackstageVersions(entries, backstageVersion, ctx); + + return { + backstageVersion, + packages: entries.toSorted((a, b) => a.name.localeCompare(b.name)), + }; +} + +/** + * Read the Backstage version from `backstage.json` in the workspace. + * Throws if `backstage:^` deps exist but no `backstage.json` is found. + */ +export function getBackstageVersion(workspacePath: string): string { + const backstageJsonPath = path.join(workspacePath, "backstage.json"); + if (!fs.existsSync(backstageJsonPath)) { + throw new Error( + "workspace has backstage:^ dependencies but no backstage.json — " + + "cannot determine Backstage version", + ); + } + const content = JSON.parse(fs.readFileSync(backstageJsonPath, "utf8")); + if (!content.version) { + throw new Error("backstage.json exists but has no 'version' field"); + } + return content.version; +} + +// --------------------------------------------------------------------------- +// yarn.lock extraction (using shared parser) +// --------------------------------------------------------------------------- + +/** + * Extract `@backstage/*` package entries resolved via `backstage:^` from a + * yarn.lock string. Returns structured entries with version and dependency + * metadata. + * + * Uses the shared `yarn-lock-parser` for structural parsing, then maps the + * parsed blocks to `BackstagePackageEntry` objects. + */ +export function extractBackstageEntries(lockContent: string): BackstagePackageEntry[] { + const lockfile = parseLockfile(lockContent); + return lockfile.blocks + .map(parseBackstageBlock) + .filter((entry): entry is BackstagePackageEntry => entry !== undefined); +} + +function parseBackstageBlock(block: LockfileBlock): BackstagePackageEntry | undefined { + const descriptor = block.descriptors.find((d) => d.includes("backstage:^")); + if (!descriptor) return undefined; + + const nameMatch = /(@backstage\/[^@]+)/.exec(descriptor); + const name = nameMatch?.[1]; + if (!name) return undefined; + + const version = getScalar(block, "version"); + if (!version) return undefined; + + const entry: BackstagePackageEntry = { name, version }; + + const deps = getStrippedMap(block, "dependencies"); + if (deps) entry.dependencies = deps; + + const peers = getStrippedMap(block, "peerDependencies"); + if (peers) entry.peerDependencies = peers; + + const peersMeta = getNestedMap(block, "peerDependenciesMeta"); + if (peersMeta) { + entry.peerDependenciesMeta = convertNestedMapValues(peersMeta); + } + + const optional = getStrippedMap(block, "optionalDependencies"); + if (optional) entry.optionalDependencies = optional; + + const bin = getStrippedMap(block, "bin"); + if (bin) entry.bin = bin; + + return entry; +} + +function stripMapQuotes(raw: { [key: string]: string }): Record { + const result: Record = {}; + for (const [key, value] of Object.entries(raw)) { + result[key.replace(/^"|"$/g, "")] = value.replace(/^"|"$/g, ""); + } + return result; +} + +function getStrippedMap( + block: LockfileBlock, + fieldName: string, +): Record | undefined { + const raw = getMap(block, fieldName); + if (!raw) return undefined; + const stripped = stripMapQuotes(raw); + return Object.keys(stripped).length > 0 ? stripped : undefined; +} + +function convertNestedMapValues(peersMeta: { + [key: string]: { [prop: string]: string }; +}): Record> | undefined { + const entries = Object.entries(peersMeta); + if (entries.length === 0) return undefined; + const converted: Record> = {}; + for (const [pkg, props] of entries) { + const record: Record = {}; + converted[pkg] = record; + for (const [key, val] of Object.entries(props)) { + const unquoted = val.replace(/^"|"$/g, ""); + let value: unknown; + if (unquoted === "true") { + value = true; + } else if (unquoted === "false") { + value = false; + } else { + value = unquoted; + } + record[key] = value; + } + } + return converted; +} + +// --------------------------------------------------------------------------- +// Backstage version validation +// --------------------------------------------------------------------------- + +async function validateBackstageVersions( + entries: BackstagePackageEntry[], + backstageVersion: string, + ctx: ModuleContext, +): Promise { + const url = `${VERSIONS_BACKSTAGE_IO}/${backstageVersion}/manifest.json`; + ctx.log(`Validating against ${url}`); + + const response = await fetch(url); + if (!response.ok) { + throw new Error( + `failed to fetch Backstage manifest for ${backstageVersion}: HTTP ${response.status}`, + ); + } + + const manifest: unknown = await response.json(); + if ( + typeof manifest !== "object" || + manifest === null || + !("packages" in manifest) || + !Array.isArray(manifest.packages) + ) { + throw new Error(`invalid Backstage manifest response from ${url}`); + } + const versionMap = new Map(); + for (const pkg of manifest.packages) { + if ( + typeof pkg === "object" && + pkg !== null && + "name" in pkg && + "version" in pkg && + typeof pkg.name === "string" && + typeof pkg.version === "string" + ) { + versionMap.set(pkg.name, pkg.version); + } + } + + const mismatches: string[] = []; + for (const entry of entries) { + const expected = versionMap.get(entry.name); + if (expected && expected !== entry.version) { + mismatches.push(`${entry.name}: yarn.lock has ${entry.version}, manifest has ${expected}`); + } + } + + if (mismatches.length > 0) { + throw new Error( + `backstage version mismatch between yarn.lock and versions.backstage.io:\n` + + mismatches.join("\n"), + ); + } + + ctx.log(`All ${entries.length} entries validated against Backstage ${backstageVersion}`); +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +function writeJson(filePath: string, data: unknown): void { + fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n"); +} diff --git a/prepare-sources/lib/test-utils.ts b/prepare-sources/lib/test-utils.ts index fcce6fe..99d94b6 100644 --- a/prepare-sources/lib/test-utils.ts +++ b/prepare-sources/lib/test-utils.ts @@ -5,6 +5,68 @@ import { describe, expect, it, vi } from "vite-plus/test"; import { readSourceFile } from "./source.ts"; import type { ModuleContext } from "./pipeline.ts"; +// --------------------------------------------------------------------------- +// Fetch mocking +// --------------------------------------------------------------------------- + +export type MockFetchResponse = { + body: unknown; + status?: number; + ok?: boolean; +}; + +function isMockFetchResponse(value: object): value is MockFetchResponse { + return "body" in value; +} + +function jsonResponse(body: unknown, status = 200): Response { + return new Response(JSON.stringify(body), { + status, + headers: { "Content-Type": "application/json" }, + }); +} + +/** + * Stub global `fetch` with a URL → response mapping. + * + * Values can be plain objects (treated as 200 OK JSON bodies) or + * `MockFetchResponse` objects for control over status/ok. + * + * Unmocked URLs cause the returned `fetch` to throw, making tests fail fast + * if unexpected network calls happen. Call `vi.restoreAllMocks()` (or rely on + * the `afterEach` below) to restore the real `fetch`. + */ +export function mockFetch( + mappings: Record, + options?: { unmockedBehavior?: "throw" | "empty" }, +): void { + const behavior = options?.unmockedBehavior ?? "throw"; + vi.stubGlobal("fetch", (input: string | URL | Request): Promise => { + let url: string; + if (typeof input === "string") { + url = input; + } else if (input instanceof URL) { + url = input.href; + } else { + url = input.url; + } + if (url in mappings) { + const raw = mappings[url]; + if (raw === undefined) { + return Promise.reject(new Error(`unmocked fetch: ${url}`)); + } + if (isMockFetchResponse(raw)) { + return Promise.resolve(jsonResponse(raw.body, raw.status ?? 200)); + } + return Promise.resolve(jsonResponse(raw)); + } + if (behavior === "empty") { + return Promise.resolve(jsonResponse(null, 404)); + } + return Promise.reject(new Error(`unmocked fetch: ${url}`)); + }); +} + /** Assertion helpers scoped to a single directory. */ export interface DirAssertions { readFile(relativePath: string): string; @@ -209,10 +271,15 @@ export function loadFixture( * * @param testDir Pass `import.meta.dirname` from your test file. * @param run The module's `run` function. + * @param options Optional hooks: + * - `setup(fixture, fixtureDir)` — called before each fixture's module run. + * Use for per-fixture mocking (e.g. `mockFetch` from network response + * fixture files). Cleanup is handled by `afterEach` / `vi.restoreAllMocks`. */ export function testInputOutputExpectations( testDir: string, run: (ctx: ModuleContext) => Promise, + options?: { setup?: (fixture: ModuleFixture, fixtureDir: string) => void }, ): void { const fixturesDir = path.join(testDir, "__fixtures__"); if (!fs.existsSync(fixturesDir)) { @@ -228,8 +295,10 @@ export function testInputOutputExpectations( describe("fixtures", () => { for (const name of fixtures) { it(name, async () => { + const fixtureDir = path.join(fixturesDir, name); using fixture = loadFixture(testDir, name); - const errorFile = path.join(fixturesDir, name, "error"); + options?.setup?.(fixture, fixtureDir); + const errorFile = path.join(fixtureDir, "error"); if (fs.existsSync(errorFile)) { const raw = fs.readFileSync(errorFile, "utf8").trim(); diff --git a/prepare-sources/lib/yarn-lock-parser.test.ts b/prepare-sources/lib/yarn-lock-parser.test.ts new file mode 100644 index 0000000..94689e9 --- /dev/null +++ b/prepare-sources/lib/yarn-lock-parser.test.ts @@ -0,0 +1,953 @@ +import { describe, expect, it } from "vitest"; +import { + type Lockfile, + type LockfileBlock, + getMap, + getNestedMap, + getScalar, + parseLockfile, + serializeBlock, + serializeLockfile, +} from "./yarn-lock-parser.ts"; + +function roundTrip(lockfile: Lockfile): string { + return serializeLockfile(lockfile); +} + +function expectFirstBlock(lockfile: Lockfile): LockfileBlock { + const block = lockfile.blocks[0]; + expect(block).toBeDefined(); + if (!block) { + throw new Error("expected block"); + } + return block; +} + +// --------------------------------------------------------------------------- +// Round-trip fidelity +// --------------------------------------------------------------------------- + +describe("round-trip fidelity", () => { + const cases: [string, string][] = [ + [ + "simple lockfile", + [ + '# This file is generated by running "yarn install" inside your project.', + "# Manual changes might be lost - proceed with caution!", + "", + "__metadata:", + " version: 8", + " cacheKey: 10c0", + "", + '"@backstage/core-plugin-api@backstage:^":', + " version: 1.10.9", + ' resolution: "@backstage/core-plugin-api@npm:1.10.9"', + " dependencies:", + ' "@backstage/types": "npm:^1.2.3"', + ' react: "npm:^18.0.0"', + " checksum: abc123", + " languageName: node", + " linkType: hard", + "", + ].join("\n"), + ], + [ + "combined keys", + [ + "__metadata:", + " version: 8", + "", + '"@aws-sdk/types@npm:^3.222.0, @aws-sdk/types@npm:^3.347.0, @aws-sdk/types@npm:^3.973.1":', + " version: 3.973.1", + ' resolution: "@aws-sdk/types@npm:3.973.1"', + " checksum: abc", + "", + ].join("\n"), + ], + [ + "nested map (peerDependenciesMeta)", + [ + "__metadata:", + " version: 8", + "", + '"@backstage/theme@backstage:^":', + " version: 0.6.3", + " peerDependencies:", + ' react: "npm:^18.0.0"', + " peerDependenciesMeta:", + " react:", + " optional: true", + " linkType: hard", + "", + ].join("\n"), + ], + [ + "unquoted simple keys in deps", + [ + "__metadata:", + " version: 8", + "", + '"ajv@npm:^8.17.1":', + " version: 8.17.1", + " dependencies:", + ' fast-deep-equal: "npm:^3.1.3"', + ' json-schema-traverse: "npm:^1.0.0"', + ' require-from-string: "npm:^2.0.2"', + ' uri-js: "npm:^4.4.1"', + " linkType: hard", + "", + ].join("\n"), + ], + [ + "workspace block", + [ + "__metadata:", + " version: 8", + "", + '"@test/root@workspace:.":', + " version: 0.0.0-use.local", + ' resolution: "@test/root@workspace:."', + " languageName: unknown", + " linkType: soft", + "", + ].join("\n"), + ], + [ + "block with bin", + [ + "__metadata:", + " version: 8", + "", + '"@backstage/core-plugin-api@backstage:^":', + " version: 1.10.9", + " bin:", + " backstage-core: ./dist/cli.js", + " checksum: abc123", + "", + ].join("\n"), + ], + [ + "multiple blocks", + [ + "__metadata:", + " version: 8", + "", + '"pkg-a@npm:^1.0.0":', + " version: 1.0.0", + " linkType: hard", + "", + '"pkg-b@npm:^2.0.0":', + " version: 2.0.0", + " dependencies:", + ' pkg-a: "npm:^1.0.0"', + " linkType: hard", + "", + ].join("\n"), + ], + ]; + + it.each(cases)("%s", (_name, input) => { + const lockfile = parseLockfile(input); + const output = serializeLockfile(lockfile); + expect(output).toBe(input); + }); +}); + +// --------------------------------------------------------------------------- +// Parsing +// --------------------------------------------------------------------------- + +describe("parseLockfile", () => { + it("captures the preamble including __metadata", () => { + const input = [ + "# comment", + "", + "__metadata:", + " version: 8", + " cacheKey: 10c0", + "", + '"pkg@npm:^1.0.0":', + " version: 1.0.0", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + expect(lockfile.preamble).toBe("# comment\n\n__metadata:\n version: 8\n cacheKey: 10c0"); + expect(lockfile.blocks).toHaveLength(1); + }); + + it("handles lockfile without __metadata", () => { + const input = ['"pkg@npm:^1.0.0":', " version: 1.0.0", ""].join("\n"); + + const lockfile = parseLockfile(input); + expect(lockfile.preamble).toBe(""); + expect(lockfile.blocks).toHaveLength(1); + const block = expectFirstBlock(lockfile); + expect(block.fields.version).toEqual({ + kind: "scalar", + raw: "1.0.0", + }); + }); + + it("parses combined descriptor keys", () => { + const input = [ + "__metadata:", + " version: 8", + "", + '"@aws/types@npm:^3.0.0, @aws/types@npm:^3.1.0":', + " version: 3.1.0", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.descriptors).toEqual(["@aws/types@npm:^3.0.0", "@aws/types@npm:^3.1.0"]); + }); + + it("parses scalar, map, and nested-map fields", () => { + const input = [ + "__metadata:", + " version: 8", + "", + '"@backstage/theme@backstage:^":', + " version: 0.6.3", + ' resolution: "@backstage/theme@npm:0.6.3"', + " dependencies:", + ' "@emotion/react": "npm:^11.0.0"', + " peerDependencies:", + ' react: "npm:^18.0.0"', + " peerDependenciesMeta:", + " react:", + " optional: true", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + + expect(block.fields.version).toEqual({ kind: "scalar", raw: "0.6.3" }); + expect(block.fields.resolution).toEqual({ + kind: "scalar", + raw: '"@backstage/theme@npm:0.6.3"', + }); + expect(block.fields.dependencies).toEqual({ + kind: "map", + entries: { '"@emotion/react"': '"npm:^11.0.0"' }, + }); + expect(block.fields.peerDependencies).toEqual({ + kind: "map", + entries: { react: '"npm:^18.0.0"' }, + }); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: { react: { optional: "true" } }, + }); + expect(block.fields.linkType).toEqual({ kind: "scalar", raw: "hard" }); + }); + + it("skips blank lines between blocks", () => { + const input = [ + "__metadata:", + " version: 8", + "", + "", + '"a@npm:1":', + " version: 1", + "", + "", + "", + '"b@npm:2":', + " version: 2", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + expect(lockfile.blocks).toHaveLength(2); + }); + + it("skips stray non-descriptor lines", () => { + const input = [ + "__metadata:", + " version: 8", + "", + "this is a stray line without trailing colon", + "", + '"pkg@npm:1":', + " version: 1", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + expect(lockfile.blocks).toHaveLength(1); + const block = expectFirstBlock(lockfile); + expect(block.descriptors).toEqual(["pkg@npm:1"]); + }); + + it("handles unquoted descriptor (non-standard)", () => { + const input = ["my-pkg@npm:1.0.0:", " version: 1.0.0", ""].join("\n"); + + const lockfile = parseLockfile(input); + expect(lockfile.blocks).toHaveLength(1); + const block = expectFirstBlock(lockfile); + expect(block.descriptors).toEqual(["my-pkg@npm:1.0.0"]); + }); + + it("skips mid-file comment lines", () => { + const input = [ + "__metadata:", + " version: 8", + "", + "# Inline comment between blocks", + '"pkg@npm:1":', + " version: 1", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + expect(lockfile.blocks).toHaveLength(1); + }); + + it("handles nested-map with orphan property before key", () => { + const input = [ + "__metadata:", + " version: 8", + "", + '"pkg@npm:1":', + " version: 1", + " peerDependenciesMeta:", + " orphan: true", + " react:", + " optional: true", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: { react: { optional: "true" } }, + }); + expect(block.fields.linkType).toEqual({ kind: "scalar", raw: "hard" }); + }); +}); + +// --------------------------------------------------------------------------- +// Serialization +// --------------------------------------------------------------------------- + +describe("serializeBlock", () => { + it("quotes all descriptors", () => { + const block: LockfileBlock = { + descriptors: ["pkg@npm:^1.0.0"], + fields: { version: { kind: "scalar", raw: "1.0.0" } }, + }; + const output = serializeBlock(block); + expect(output).toBe('"pkg@npm:^1.0.0":\n version: 1.0.0'); + }); + + it("serializes combined descriptors within one pair of quotes", () => { + const block: LockfileBlock = { + descriptors: ["pkg@npm:^1.0.0", "pkg@npm:^1.1.0"], + fields: { version: { kind: "scalar", raw: "1.1.0" } }, + }; + const output = serializeBlock(block); + expect(output.startsWith('"pkg@npm:^1.0.0, pkg@npm:^1.1.0":')).toBe(true); + }); +}); + +// --------------------------------------------------------------------------- +// Convenience accessors +// --------------------------------------------------------------------------- + +describe("getScalar", () => { + it("returns unquoted value", () => { + const block: LockfileBlock = { + descriptors: ["pkg@npm:1"], + fields: { + version: { kind: "scalar", raw: "1.0.0" }, + resolution: { kind: "scalar", raw: '"pkg@npm:1.0.0"' }, + }, + }; + expect(getScalar(block, "version")).toBe("1.0.0"); + expect(getScalar(block, "resolution")).toBe("pkg@npm:1.0.0"); + }); + + it("returns undefined for missing or non-scalar field", () => { + const block: LockfileBlock = { + descriptors: ["pkg@npm:1"], + fields: { + deps: { kind: "map", entries: { a: "1" } }, + }, + }; + expect(getScalar(block, "missing")).toBeUndefined(); + expect(getScalar(block, "deps")).toBeUndefined(); + }); +}); + +describe("getMap", () => { + it("returns entries", () => { + const block: LockfileBlock = { + descriptors: ["pkg@npm:1"], + fields: { + dependencies: { + kind: "map", + entries: { react: '"npm:^18.0.0"' }, + }, + }, + }; + expect(getMap(block, "dependencies")).toEqual({ + react: '"npm:^18.0.0"', + }); + }); + + it("returns undefined for missing or non-map field", () => { + const block: LockfileBlock = { + descriptors: ["pkg@npm:1"], + fields: { + version: { kind: "scalar", raw: "1" }, + }, + }; + expect(getMap(block, "missing")).toBeUndefined(); + expect(getMap(block, "version")).toBeUndefined(); + }); +}); + +describe("getNestedMap", () => { + it("returns entries", () => { + const block: LockfileBlock = { + descriptors: ["pkg@npm:1"], + fields: { + peerDependenciesMeta: { + kind: "nested-map", + entries: { react: { optional: "true" } }, + }, + }, + }; + expect(getNestedMap(block, "peerDependenciesMeta")).toEqual({ + react: { optional: "true" }, + }); + }); + + it("returns undefined for missing or non-nested-map field", () => { + const block: LockfileBlock = { + descriptors: ["pkg@npm:1"], + fields: { + version: { kind: "scalar", raw: "1" }, + }, + }; + expect(getNestedMap(block, "missing")).toBeUndefined(); + expect(getNestedMap(block, "version")).toBeUndefined(); + }); +}); + +// --------------------------------------------------------------------------- +// Mutation scenarios (for protocol-resolution) +// --------------------------------------------------------------------------- + +describe("mutation", () => { + it("allows updating a scalar value while preserving order", () => { + const input = [ + "__metadata:", + " version: 8", + "", + '"pkg@npm:^1.0.0":', + " version: 1.0.0", + ' resolution: "pkg@npm:1.0.0"', + " checksum: abc", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + block.fields.version = { kind: "scalar", raw: "2.0.0" }; + + expect(roundTrip(lockfile)).toBe(input.replace("version: 1.0.0", "version: 2.0.0")); + }); + + it("allows replacing a dependency value in a map", () => { + const input = [ + "__metadata:", + " version: 8", + "", + '"pkg@npm:^1.0.0":', + " version: 1.0.0", + " dependencies:", + ' react: "npm:^17.0.0"', + ' lodash: "npm:^4.0.0"', + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + const deps = block.fields.dependencies; + if (deps?.kind === "map") { + deps.entries.react = '"npm:^18.0.0"'; + } + + const output = roundTrip(lockfile); + expect(output).toContain('react: "npm:^18.0.0"'); + expect(output).toContain('lodash: "npm:^4.0.0"'); + expect(output.indexOf("react")).toBeLessThan(output.indexOf("lodash")); + }); + + it("allows adding a new block", () => { + const input = [ + "__metadata:", + " version: 8", + "", + '"pkg-a@npm:^1.0.0":', + " version: 1.0.0", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + lockfile.blocks.push({ + descriptors: ["pkg-b@npm:^2.0.0"], + fields: { + version: { kind: "scalar", raw: "2.0.0" }, + linkType: { kind: "scalar", raw: "hard" }, + }, + }); + + const output = roundTrip(lockfile); + expect(output).toContain('"pkg-b@npm:^2.0.0":'); + expect(output).toContain("version: 2.0.0"); + }); + + it("allows removing a block", () => { + const input = [ + "__metadata:", + " version: 8", + "", + '"pkg-a@npm:^1.0.0":', + " version: 1.0.0", + "", + '"pkg-b@npm:^2.0.0":', + " version: 2.0.0", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + lockfile.blocks = lockfile.blocks.filter((b) => { + const firstDescriptor = b.descriptors[0]; + return firstDescriptor === undefined || !firstDescriptor.includes("pkg-b"); + }); + + const output = roundTrip(lockfile); + expect(output).toContain("pkg-a"); + expect(output).not.toContain("pkg-b"); + }); + + it("allows enriching descriptors (adding a specifier)", () => { + const input = [ + "__metadata:", + " version: 8", + "", + '"@backstage/core@backstage:^":', + " version: 1.0.0", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + block.descriptors.push("@backstage/core@npm:1.0.0"); + + const output = roundTrip(lockfile); + expect(output).toContain('"@backstage/core@backstage:^, @backstage/core@npm:1.0.0":'); + }); +}); + +// --------------------------------------------------------------------------- +// Edge cases: defensive branches +// --------------------------------------------------------------------------- + +describe("parser edge cases", () => { + it("stops parsing block body on an empty line", () => { + const input = ['"pkg@npm:1":', " version: 1.0.0", "", " linkType: hard", ""].join("\n"); + + const lockfile = parseLockfile(input); + expect(lockfile.blocks).toHaveLength(1); + const block = expectFirstBlock(lockfile); + expect(block.fields.version).toEqual({ + kind: "scalar", + raw: "1.0.0", + }); + expect(block.fields.linkType).toBeUndefined(); + }); + + it("stops parsing block body on a 2-space line that is not a valid field", () => { + const input = [ + '"pkg@npm:1":', + " version: 1.0.0", + " no-colon-here", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.version).toBeDefined(); + expect(block.fields.linkType).toBeUndefined(); + }); + + it("handles a section header with no sub-content", () => { + const input = [ + '"pkg@npm:1":', + " version: 1.0.0", + " dependencies:", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.dependencies).toBeUndefined(); + expect(block.fields.linkType).toEqual({ kind: "scalar", raw: "hard" }); + }); + + it("skips malformed 4-space map entries", () => { + const input = [ + '"pkg@npm:1":', + " version: 1.0.0", + " dependencies:", + " valid-dep: 1.0.0", + " no-colon-garbage", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.dependencies).toEqual({ + kind: "map", + entries: { "valid-dep": "1.0.0" }, + }); + }); + + it("skips malformed 6-space nested-map property lines", () => { + const input = [ + '"pkg@npm:1":', + " peerDependenciesMeta:", + " react:", + " optional: true", + " garbage-no-colon", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: { react: { optional: "true" } }, + }); + }); + + it("breaks nested-map on a 4-space line that is not a key header", () => { + const input = [ + '"pkg@npm:1":', + " peerDependenciesMeta:", + " react:", + " optional: true", + " not-a-key-header 1.0.0", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: { react: { optional: "true" } }, + }); + }); + + it("stops parsing on degenerate field lines with empty name", () => { + const input = [ + '"pkg@npm:1":', + " version: 1.0.0", + " : orphan-value", + " :", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.version).toBeDefined(); + expect(block.fields[""]).toBeUndefined(); + expect(block.fields.linkType).toBeUndefined(); + }); + + it("stops parsing on field lines with colon not followed by whitespace", () => { + const input = [ + '"pkg@npm:1":', + " version: 1.0.0", + " name:value-no-space", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.version).toBeDefined(); + expect(block.fields.name).toBeUndefined(); + expect(block.fields.linkType).toBeUndefined(); + }); + + it("handles map keys containing colons", () => { + const input = [ + '"pkg@npm:1":', + " dependencies:", + ' "key:with:colons": "npm:^1.0.0"', + " simple-key: value", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.dependencies).toEqual({ + kind: "map", + entries: { + '"key:with:colons"': '"npm:^1.0.0"', + "simple-key": "value", + }, + }); + }); + + it("handles nested-map keys containing colons", () => { + const input = [ + '"pkg@npm:1":', + " peerDependenciesMeta:", + " key:sub:", + " optional: true", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: { "key:sub": { optional: "true" } }, + }); + }); + + it("handles nested-map property names containing colons", () => { + const input = [ + '"pkg@npm:1":', + " peerDependenciesMeta:", + " react:", + " prop:name: true", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: { react: { "prop:name": "true" } }, + }); + }); + + it("drops orphan 4-space line that appears before any field header", () => { + const input = ['"pkg@npm:1":', " orphan-deep-line: value", " version: 1.0.0", ""].join( + "\n", + ); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.version).toEqual({ kind: "scalar", raw: "1.0.0" }); + }); + + it("stops block parsing on stray non-indented line before first field", () => { + const input = ['"pkg@npm:1":', "stray-line-at-top", " version: 1.0.0", ""].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.version).toBeUndefined(); + }); + + it("stops block parsing on stray non-indented line inside a map section", () => { + const input = [ + '"pkg@npm:1":', + " dependencies:", + " valid: 1.0.0", + "stray-line", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.dependencies).toEqual({ + kind: "map", + entries: { valid: "1.0.0" }, + }); + expect(block.fields.linkType).toBeUndefined(); + }); + + it("stops block parsing on stray non-indented line inside a nested-map section", () => { + const input = [ + '"pkg@npm:1":', + " peerDependenciesMeta:", + " react:", + " optional: true", + "stray-line", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: { react: { optional: "true" } }, + }); + expect(block.fields.linkType).toBeUndefined(); + }); + + it("does not misidentify 5-space lines as nested-map headers", () => { + const input = [ + '"pkg@npm:1":', + " section:", + " five-space-key: value", + " normal-key: value", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + // 5-space line is NOT a nested-map header → section is parsed as flat map + expect(block.fields.section).toEqual({ + kind: "map", + entries: { " five-space-key": "value", "normal-key": "value" }, + }); + }); + + it("skips map entries with empty key (colon at indent boundary)", () => { + const input = [ + '"pkg@npm:1":', + " dependencies:", + " : empty-key-value", + " valid: 1.0.0", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.dependencies).toEqual({ + kind: "map", + entries: { valid: "1.0.0" }, + }); + }); + + it("skips nested-map key headers with empty key", () => { + const input = [ + '"pkg@npm:1":', + " peerDependenciesMeta:", + " :", + " optional: true", + " react:", + " optional: false", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: { react: { optional: "false" } }, + }); + }); + + it("skips nested-map properties with empty prop name", () => { + const input = [ + '"pkg@npm:1":', + " peerDependenciesMeta:", + " react:", + " : empty-prop-value", + " optional: true", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: { react: { optional: "true" } }, + }); + }); + + it("produces empty map when all entries are malformed", () => { + const input = [ + '"pkg@npm:1":', + " dependencies:", + " no-colon-here", + " also-no-colon", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.dependencies).toEqual({ + kind: "map", + entries: {}, + }); + }); + + it("produces empty nested-map when all keys are malformed", () => { + const input = [ + '"pkg@npm:1":', + " peerDependenciesMeta:", + " not-a-key-header 1.0.0", + " orphan: true", + " linkType: hard", + "", + ].join("\n"); + + const lockfile = parseLockfile(input); + const block = expectFirstBlock(lockfile); + expect(block.fields.peerDependenciesMeta).toEqual({ + kind: "nested-map", + entries: {}, + }); + }); + + it("serializes lockfile with empty preamble", () => { + const lockfile: Lockfile = { + preamble: "", + blocks: [ + { + descriptors: ["pkg@npm:1"], + fields: { version: { kind: "scalar", raw: "1.0.0" } }, + }, + ], + }; + const output = serializeLockfile(lockfile); + expect(output).toBe('\n"pkg@npm:1":\n version: 1.0.0\n'); + }); +}); + +// --------------------------------------------------------------------------- +// Real-world lockfile round-trip +// --------------------------------------------------------------------------- + +describe("real-world fixture round-trip", () => { + it("round-trips the monorepo-with-backstage fixture", async () => { + const fs = await import("node:fs"); + const path = await import("node:path"); + const fixturePath = path.join( + import.meta.dirname, + "modules/generate-manifests/__fixtures__/monorepo-with-backstage/input/workspace/yarn.lock", + ); + const content = fs.readFileSync(fixturePath, "utf8"); + const lockfile = parseLockfile(content); + const output = serializeLockfile(lockfile); + expect(output).toBe(content); + }); +}); diff --git a/prepare-sources/lib/yarn-lock-parser.ts b/prepare-sources/lib/yarn-lock-parser.ts new file mode 100644 index 0000000..482d2ec --- /dev/null +++ b/prepare-sources/lib/yarn-lock-parser.ts @@ -0,0 +1,392 @@ +/** + * Zero-dependency Yarn Berry lockfile (SYML) parser and serializer. + * + * Designed for round-trip fidelity: parse → serialize produces output + * identical to the input for unmodified content. Field and entry ordering + * is preserved via JavaScript object insertion-order guarantees (ES2015+). + * + * Used by `generate-manifests` (read-only extraction), `protocol-resolution` + * (block replacement, descriptor enrichment, value rewriting), `package-cleanup` + * (block removal), and `validate` (structural comparison). + */ + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +export type Lockfile = { + preamble: string; + blocks: LockfileBlock[]; +}; + +export type LockfileBlock = { + descriptors: string[]; + fields: { [name: string]: LockfileField }; +}; + +export type LockfileField = ScalarField | MapField | NestedMapField; + +export type ScalarField = { kind: "scalar"; raw: string }; +export type MapField = { kind: "map"; entries: { [key: string]: string } }; +export type NestedMapField = { + kind: "nested-map"; + entries: { [key: string]: { [prop: string]: string } }; +}; + +// --------------------------------------------------------------------------- +// String-based matchers — no regex captures, no `string | undefined` +// +// Each function uses indexOf + substring + trimStart/trim to parse SYML +// field lines. All return types are fully narrowed (`string`, not +// `string | undefined`), so no v8-ignore guards are needed. +// --------------------------------------------------------------------------- + +/** + * Match a 2-space scalar field: ` name: value` + * Equivalent to `/^ ([^:]+):\s+(.+)$/` + * Name cannot contain colons → first colon is the separator. + */ +function matchScalar(line: string): { name: string; raw: string } | null { + const colonPos = line.indexOf(":", 2); + if (colonPos === -1) return null; + const name = line.substring(2, colonPos); + if (name.length === 0) return null; + const rest = line.substring(colonPos + 1); + const raw = rest.trimStart(); + if (raw.length === 0 || rest.length === raw.length) return null; + return { name, raw }; +} + +/** + * Match a 2-space section header: ` name:` (with optional trailing whitespace) + * Equivalent to `/^ ([^:]+):\s*$/` + * Name cannot contain colons → first colon is the separator. + */ +function matchSectionHeader(line: string): string | null { + const colonPos = line.indexOf(":", 2); + if (colonPos === -1) return null; + const name = line.substring(2, colonPos); + if (name.length === 0) return null; + const rest = line.substring(colonPos + 1); + if (rest.trim().length !== 0) return null; + return name; +} + +/** + * Match a 4-space map entry: ` key: value` + * Equivalent to `/^\s{4}(.+?):\s+(.+)$/` + * Key may contain colons (non-greedy) → try each colon left-to-right. + */ +function matchMapEntry(line: string): [key: string, value: string] | null { + let colonPos = line.indexOf(":", 4); + while (colonPos !== -1) { + const rest = line.substring(colonPos + 1); + const value = rest.trimStart(); + if (rest.length !== value.length && value.length > 0) { + const key = line.substring(4, colonPos); + if (key.length > 0) return [key, value]; + } + colonPos = line.indexOf(":", colonPos + 1); + } + return null; +} + +/** + * Match a 4-space nested-map key header: ` key:` (with optional trailing ws) + * Equivalent to `/^\s{4}(.+?):\s*$/` + * Key may contain colons → try each colon left-to-right. + */ +function matchNestedKey(line: string): string | null { + let colonPos = line.indexOf(":", 4); + while (colonPos !== -1) { + const rest = line.substring(colonPos + 1); + if (rest.trim().length === 0) { + const key = line.substring(4, colonPos); + if (key.length > 0) return key; + } + colonPos = line.indexOf(":", colonPos + 1); + } + return null; +} + +/** + * Match a 6-space nested-map property: ` prop: value` + * Equivalent to `/^\s{6}(.+?):\s+(.+)$/` + * Prop may contain colons → try each colon left-to-right. + */ +function matchNestedProp(line: string): [prop: string, value: string] | null { + let colonPos = line.indexOf(":", 6); + while (colonPos !== -1) { + const rest = line.substring(colonPos + 1); + const value = rest.trimStart(); + if (rest.length !== value.length && value.length > 0) { + const prop = line.substring(6, colonPos); + if (prop.length > 0) return [prop, value]; + } + colonPos = line.indexOf(":", colonPos + 1); + } + return null; +} + +/** + * Detect whether a 4-space line is a nested-map key header (e.g. ` react:`) + * rather than a flat map entry (e.g. ` react: "npm:^18"`). + * Equivalent to `/^\s{4}\S.*:\s*$/` — 4-space indent, non-space start, colon + * at end with optional trailing whitespace. + */ +function isNestedMapHeader(line: string): boolean { + if (!line.startsWith(" ") || line.charAt(4) === " ") return false; + const colonPos = line.indexOf(":", 4); + if (colonPos === -1) return false; + return line.substring(colonPos + 1).trim().length === 0; +} + +// --------------------------------------------------------------------------- +// Structured grouping types — typed fields instead of raw string[] +// --------------------------------------------------------------------------- + +type BlockGroup = { descriptor: string; body: string[] }; +type FieldGroup = { header: string; subLines: string[] }; + +// --------------------------------------------------------------------------- +// Parser +// --------------------------------------------------------------------------- + +export function parseLockfile(content: string): Lockfile { + const lines = content.split("\n"); + + const preambleEnd = findPreambleEnd(lines); + const preamble = lines.slice(0, preambleEnd).join("\n"); + + const blockLines = lines.slice(preambleEnd); + const blocks = splitIntoBlockGroups(blockLines).map(parseBlockGroup); + + return { preamble, blocks }; +} + +/** + * Find where the preamble ends (comment lines, blank lines, __metadata block). + * Returns the index of the first non-preamble line. + */ +function findPreambleEnd(lines: string[]): number { + let i = 0; + for (const line of lines) { + if (line.startsWith("#") || line === "") { + i++; + } else if (line.startsWith("__metadata:")) { + i++; // the __metadata: line itself + for (const metaLine of lines.slice(i)) { + if (!metaLine.startsWith(" ")) break; + i++; + } + break; + } else { + break; + } + } + return i; +} + +/** + * Split lines into block groups, where each group starts with a descriptor + * line (starts at column 0, ends with ":") and includes all following + * indented (2+-space) body lines. Blank lines and 0-space non-descriptor + * lines stop body collection — matching the original parser's strict + * block-termination behavior. + */ +function splitIntoBlockGroups(lines: string[]): BlockGroup[] { + const groups: BlockGroup[] = []; + let current: BlockGroup | null = null; + for (const line of lines) { + if (!line.startsWith(" ") && !line.startsWith("#") && line.endsWith(":")) { + current = { descriptor: line, body: [] }; + groups.push(current); + } else if (current !== null && line.startsWith(" ")) { + current.body.push(line); + } else { + current = null; + } + } + return groups; +} + +function parseBlockGroup(group: BlockGroup): LockfileBlock { + const descriptors = parseDescriptors(group.descriptor.slice(0, -1)); + const fields = parseFields(group.body); + return { descriptors, fields }; +} + +function parseDescriptors(raw: string): string[] { + const trimmed = raw.trim(); + if (trimmed.startsWith('"') && trimmed.endsWith('"')) { + return trimmed.slice(1, -1).split(", "); + } + return [trimmed]; +} + +/** + * Group body lines by top-level field (2-space indent), then parse each + * group into a LockfileField. + */ +function parseFields(bodyLines: string[]): { [name: string]: LockfileField } { + const fields: { [name: string]: LockfileField } = {}; + + for (const { header, subLines } of groupByField(bodyLines)) { + const scalar = matchScalar(header); + if (scalar) { + fields[scalar.name] = { kind: "scalar", raw: scalar.raw }; + continue; + } + + const sectionName = matchSectionHeader(header); + if (sectionName && subLines.length > 0) { + const isNested = subLines.some((l) => l.startsWith(" ") || isNestedMapHeader(l)); + if (isNested) { + fields[sectionName] = parseNestedMapLines(subLines); + } else { + fields[sectionName] = parseMapLines(subLines); + } + continue; + } + if (sectionName) continue; // valid section header with no sub-content + break; // unrecognized line — stop parsing (matches original behavior) + } + + return fields; +} + +/** + * Group body lines so that each 2-space line starts a new group, and + * deeper-indented lines (4+) are appended to the current group. + * Returns structured objects with typed fields. + */ +function groupByField(lines: string[]): FieldGroup[] { + const groups: FieldGroup[] = []; + let current: FieldGroup | null = null; + for (const line of lines) { + if (line.startsWith(" ") && !line.startsWith(" ")) { + current = { header: line, subLines: [] }; + groups.push(current); + } else if (current !== null) { + current.subLines.push(line); + } + } + return groups; +} + +function parseMapLines(lines: string[]): MapField { + const entries: { [key: string]: string } = {}; + for (const line of lines) { + const kv = matchMapEntry(line); + if (kv) { + entries[kv[0]] = kv[1]; + } + } + return { kind: "map", entries }; +} + +function parseNestedMapLines(lines: string[]): NestedMapField { + const entries: { [key: string]: { [prop: string]: string } } = {}; + let currentEntry: { [prop: string]: string } | null = null; + + for (const line of lines) { + if (line.startsWith(" ")) { + if (currentEntry) { + const pv = matchNestedProp(line); + if (pv) { + currentEntry[pv[0]] = pv[1]; + } + } + continue; + } + + const key = matchNestedKey(line); + if (key) { + currentEntry = {}; + entries[key] = currentEntry; + } + } + + return { kind: "nested-map", entries }; +} + +// --------------------------------------------------------------------------- +// Serializer +// --------------------------------------------------------------------------- + +export function serializeLockfile(lockfile: Lockfile): string { + const parts: string[] = []; + + if (lockfile.preamble) { + parts.push(lockfile.preamble); + } + + for (const block of lockfile.blocks) { + parts.push("", serializeBlock(block)); + } + + return parts.join("\n") + "\n"; +} + +export function serializeBlock(block: LockfileBlock): string { + const descriptorLine = `"${block.descriptors.join(", ")}":`; + const lines = [descriptorLine]; + + for (const [name, field] of Object.entries(block.fields)) { + switch (field.kind) { + case "scalar": + lines.push(` ${name}: ${field.raw}`); + break; + case "map": + lines.push(` ${name}:`); + for (const [key, value] of Object.entries(field.entries)) { + lines.push(` ${key}: ${value}`); + } + break; + case "nested-map": + lines.push(` ${name}:`); + for (const [key, props] of Object.entries(field.entries)) { + lines.push(` ${key}:`); + for (const [prop, value] of Object.entries(props)) { + lines.push(` ${prop}: ${value}`); + } + } + break; + /* v8 ignore next 4 -- exhaustive switch; compile-time guarantee */ + default: { + const exhaustiveCheck: never = field; + return exhaustiveCheck; + } + } + } + + return lines.join("\n"); +} + +// --------------------------------------------------------------------------- +// Convenience accessors +// --------------------------------------------------------------------------- + +export function getScalar(block: LockfileBlock, fieldName: string): string | undefined { + const field = block.fields[fieldName]; + if (field?.kind !== "scalar") return undefined; + return field.raw.replace(/^"|"$/g, ""); +} + +export function getMap( + block: LockfileBlock, + fieldName: string, +): { [key: string]: string } | undefined { + const field = block.fields[fieldName]; + if (field?.kind !== "map") return undefined; + return field.entries; +} + +export function getNestedMap( + block: LockfileBlock, + fieldName: string, +): { [key: string]: { [prop: string]: string } } | undefined { + const field = block.fields[fieldName]; + if (field?.kind !== "nested-map") return undefined; + return field.entries; +} From 76526d735ea8a8fe042ce0e7f511026fcc59469b Mon Sep 17 00:00:00 2001 From: David Festal Date: Thu, 10 Sep 2026 21:51:59 +0200 Subject: [PATCH 2/4] feat(prepare-sources): implement `plugin-removal` pipeline module Intersect `plugins-list.yaml` with `rhdh-supported-packages.txt` for the current workspace, preserve packages referenced by `dist-dynamic/embedded/*/package.json`, remove infrastructure directories (`packages/app`, `packages/backend`, `.storybook`, `examples/`, `node_modules`), and delete remaining non-supported plugin directories. Rewrite the filtered `plugins-list.yaml` back to the overlay path, preserving full lines including export CLI args. Expose `overlayRepoRoot` on `PipelineInputs` so tier-list files can be read from the overlay repository root instead of resolving `../..` inside the module. Update the fixture loader to support an `input/overlay-root/` directory for tier-list fixtures. Add the module implementation, unit tests, fixtures, and README.md; wire the module into the pipeline runner. Assisted-by: Cursor Signed-off-by: David Festal Co-authored-by: Cursor Signed-off-by: David Festal --- prepare-sources/lib/cli.test.ts | 1 + prepare-sources/lib/modules.test.ts | 1 + prepare-sources/lib/modules.ts | 3 +- .../lib/modules/plugin-removal/DESIGN.md | 164 +++++++++++++ .../lib/modules/plugin-removal/README.md | 98 ++++++++ .../overlay-root/rhdh-supported-packages.txt | 1 + .../input/overlay/plugins-list.yaml | 1 + .../input/overlay/source.json | 6 + .../input/workspace/package.json | 5 + .../plugins/another-lib-source/package.json | 4 + .../plugins/embedded-lib-source/package.json | 4 + .../embedded/another-lib/package.json | 4 + .../embedded/embedded-lib/package.json | 4 + .../plugins/exported-plugin/package.json | 4 + .../plugins/unrelated-pkg/package.json | 4 + .../output/overlay/plugins-list.yaml | 1 + .../output/overlay/source.json | 6 + .../output/workspace/package.json | 5 + .../plugins/another-lib-source/package.json | 4 + .../plugins/embedded-lib-source/package.json | 4 + .../embedded/another-lib/package.json | 4 + .../embedded/embedded-lib/package.json | 4 + .../plugins/exported-plugin/package.json | 4 + .../overlay-root/rhdh-supported-packages.txt | 4 + .../input/overlay/plugins-list.yaml | 8 + .../input/overlay/source.json | 6 + .../workspace/examples/demo/package.json | 4 + .../input/workspace/package.json | 9 + .../workspace/packages/app-next/package.json | 4 + .../input/workspace/packages/app/package.json | 4 + .../workspace/packages/backend/package.json | 4 + .../packages/gitlab-backend/package.json | 4 + .../workspace/packages/gitlab/package.json | 4 + .../plugins/keep-plugin/.storybook/main.ts | 1 + .../keep-plugin/dist-dynamic/package.json | 5 + .../plugins/keep-plugin/package.json | 4 + .../plugins/keep-with-args/package.json | 4 + .../plugins/remove-plugin/package.json | 4 + .../output/overlay/plugins-list.yaml | 6 + .../output/overlay/source.json | 6 + .../output/workspace/package.json | 9 + .../workspace/packages/gitlab/package.json | 4 + .../keep-plugin/dist-dynamic/package.json | 5 + .../plugins/keep-plugin/package.json | 4 + .../plugins/keep-with-args/package.json | 4 + .../overlay-root/rhdh-supported-packages.txt | 2 + .../input/overlay/plugins-list.yaml | 2 + .../input/overlay/source.json | 6 + .../input/workspace/package.json | 5 + .../workspace/plugins/alpha/package.json | 4 + .../input/workspace/plugins/beta/package.json | 4 + .../output/overlay/plugins-list.yaml | 0 .../output/overlay/source.json | 6 + .../output/workspace/package.json | 5 + .../error | 1 + .../overlay-root/rhdh-supported-packages.txt | 1 + .../input/overlay/source.json | 6 + .../input/workspace/package.json | 4 + .../error | 1 + .../input/overlay/plugins-list.yaml | 1 + .../input/overlay/source.json | 6 + .../input/workspace/package.json | 4 + .../lib/modules/plugin-removal/index.test.ts | 159 +++++++++++++ .../lib/modules/plugin-removal/index.ts | 216 ++++++++++++++++++ prepare-sources/lib/pipeline.test.ts | 4 +- prepare-sources/lib/pipeline.ts | 5 +- prepare-sources/lib/test-utils.ts | 40 +++- 67 files changed, 917 insertions(+), 8 deletions(-) create mode 100644 prepare-sources/lib/modules/plugin-removal/DESIGN.md create mode 100644 prepare-sources/lib/modules/plugin-removal/README.md create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay-root/rhdh-supported-packages.txt create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay/plugins-list.yaml create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/another-lib-source/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/embedded-lib-source/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/dist-dynamic/embedded/another-lib/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/dist-dynamic/embedded/embedded-lib/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/unrelated-pkg/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/overlay/plugins-list.yaml create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/overlay/source.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/another-lib-source/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/embedded-lib-source/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/dist-dynamic/embedded/another-lib/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/dist-dynamic/embedded/embedded-lib/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay-root/rhdh-supported-packages.txt create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay/plugins-list.yaml create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/examples/demo/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/app-next/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/app/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/backend/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/gitlab-backend/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/gitlab/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/.storybook/main.ts create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/dist-dynamic/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-with-args/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/remove-plugin/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/overlay/plugins-list.yaml create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/overlay/source.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/packages/gitlab/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-plugin/dist-dynamic/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-plugin/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-with-args/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay-root/rhdh-supported-packages.txt create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay/plugins-list.yaml create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/plugins/alpha/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/plugins/beta/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/overlay/plugins-list.yaml create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/overlay/source.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/error create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/overlay-root/rhdh-supported-packages.txt create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/error create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/overlay/plugins-list.yaml create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/plugin-removal/index.test.ts create mode 100644 prepare-sources/lib/modules/plugin-removal/index.ts diff --git a/prepare-sources/lib/cli.test.ts b/prepare-sources/lib/cli.test.ts index e0ed473..c61453f 100644 --- a/prepare-sources/lib/cli.test.ts +++ b/prepare-sources/lib/cli.test.ts @@ -90,6 +90,7 @@ describe("main", () => { const inputs = { workspacePath: "/ws", overlayPath: "/ov", + overlayRepoRoot: "/", source: { repo: "https://github.com/example/repo", "repo-ref": "main", diff --git a/prepare-sources/lib/modules.test.ts b/prepare-sources/lib/modules.test.ts index b18c254..6cf2c9d 100644 --- a/prepare-sources/lib/modules.test.ts +++ b/prepare-sources/lib/modules.test.ts @@ -29,6 +29,7 @@ describe("MODULES", () => { await stub.run({ workspacePath: "/tmp/ws", overlayPath: "/tmp/overlay", + overlayRepoRoot: "/tmp", source: { repo: "https://github.com/example/repo", "repo-ref": "main", diff --git a/prepare-sources/lib/modules.ts b/prepare-sources/lib/modules.ts index d3e627a..bfd37a1 100644 --- a/prepare-sources/lib/modules.ts +++ b/prepare-sources/lib/modules.ts @@ -2,6 +2,7 @@ import type { ModuleContext, PipelineModule } from "./pipeline.ts"; import { run as hermeticPrep } from "./modules/hermetic-prep/index.ts"; import { run as makeSelfContained } from "./modules/make-self-contained/index.ts"; import { run as generateManifests } from "./modules/generate-manifests/index.ts"; +import { run as pluginRemoval } from "./modules/plugin-removal/index.ts"; async function notImplemented(ctx: ModuleContext): Promise { ctx.log("not yet implemented"); @@ -12,7 +13,7 @@ export const MODULES: readonly PipelineModule[] = [ { name: "seed-frontend-lockfiles", run: notImplemented }, { name: "make-self-contained", run: makeSelfContained }, { name: "generate-manifests", run: generateManifests }, - { name: "plugin-removal", run: notImplemented }, + { name: "plugin-removal", run: pluginRemoval }, { name: "file-cleanup", run: notImplemented }, { name: "protocol-resolution", run: notImplemented }, { name: "package-cleanup", run: notImplemented }, diff --git a/prepare-sources/lib/modules/plugin-removal/DESIGN.md b/prepare-sources/lib/modules/plugin-removal/DESIGN.md new file mode 100644 index 0000000..1e04f19 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/DESIGN.md @@ -0,0 +1,164 @@ +# plugin-removal — design (grill-with-docs) + +Pre-implementation design captured from the [RHIDP-15835](https://redhat.atlassian.net/browse/RHIDP-15835) grilling session. **Implement against this document**; keep `README.md` as the post-implementation module guide. + +Related: [source-preparation-design-decisions.md](../../../docs/source-preparation-design-decisions.md) §5, §11. + +--- + +## Language + +**Supported plugin:** +A plugin whose `workspace/plugin-path` entry appears in `rhdh-supported-packages.txt`. +_Avoid_: GA plugin, production plugin (support tier is expressed elsewhere). + +**Surviving plugin:** +A plugin directory kept on disk after scrubbing — either listed in the filtered `plugins-list.yaml` or preserved as an embedded package. +_Avoid_: exported plugin (export happens again later in `re-export`). + +**Embedded package:** +A workspace package whose npm `name` appears under `*/dist-dynamic/embedded/*/package.json` from the initial export. Preserved even when not listed in `plugins-list.yaml`, so re-export does not fall back to npm and drift versions. +_Avoid_: bundled dependency (too vague). + +**Infrastructure package:** +App/backend shell directories removed before plugin scanning — not plugin exports. Examples: `packages/app`, `packages/backend`, `packages/app-next`, `.storybook`, top-level `examples/`, `node_modules`. +_Avoid_: scaffold (ambiguous). + +## Relationships + +- A **Supported plugin** is always a **Surviving plugin** +- An **Embedded package** may be a **Surviving plugin** without being a **Supported plugin** +- **Infrastructure packages** are never **Surviving plugins** +- Filtered `plugins-list.yaml` lists only **Supported plugins** (full lines preserved, including CLI args) + +## Example dialogue + +> **Dev:** "Why is `plugins/orchestrator-common` still on disk after scrubbing even though it's not in `plugins-list.yaml`?" +> +> **Domain expert:** "Because a surviving exported plugin embedded it — check `dist-dynamic/embedded/`. We preserve **Embedded packages** by npm `name`, not by plugins-list path." +> +> **Dev:** "Should we delete community plugin metadata from the overlay?" +> +> **Domain expert:** "No — that's catalog assembly, not **plugin-removal**. This module only scrubs **plugin source** in the workspace checkout." +> +> **Dev:** "Does `rhdh-community-packages.txt` filter metadata YAML inside a workspace?" +> +> **Domain expert:** "No. Per-file metadata filtering uses `spec.support` in `remove-pre-GA-entities.js`, driven by `rhdh-supported-packages.txt` and `default.packages.yaml` — not the community list. Community tier is used elsewhere (compatibility checks, wiki badges, mandatory PR labeling)." + +## Flagged ambiguities + +- RHIDP-15835 mentions "community-tier plugins (filtered by the support-tier files)" — for **source scrubbing**, community plugins are excluded because they are **not** on the supported whitelist. `rhdh-community-packages.txt` is **not** an input to this module. +- Test/dev cleanup (`*.test.ts`, `__tests__/`, `dev/`, `e2e-tests/`) lives in `file-cleanup` per design doc §11, even though `sync-midstream.sh` runs it in the same loop (lines 917–924). +- Catalog / metadata preservation is out of scope — overlay `metadata/*.yaml` and `catalog-entities/` are untouched. + +--- + +## Resolved decisions + +### 1. Whitelist from `rhdh-supported-packages.txt` only + +Keep plugins whose `workspace/plugin-path` is in `rhdh-supported-packages.txt`. Do not read `rhdh-community-packages.txt` for source scrubbing. + +`sync-midstream.sh` also has a separate community blacklist pass (lines 1066–1094) at repo scope; in the per-workspace pipeline the whitelist intersection is sufficient. + +### 2. `overlayRepoRoot` on `PipelineInputs` + +Tier list files live at the overlay **repository** root (`rhdh-supported-packages.txt`), while `ctx.overlayPath` is `overlay-repo/workspaces//`. + +Expose `ctx.overlayRepoRoot` on `PipelineInputs`, derived in `loadPipelineInputs` as `path.resolve(overlayPath, '../..')`. Do **not** traverse with `../..` inside the module (security scanner / linter concerns). + +### 3. Pipeline starts after initial export + +The CLI runs after `export-dynamic.yaml` has completed an initial `rhdh-cli plugin export`. At `plugin-removal` time, `dist-dynamic/` and `dist-dynamic/embedded/` already exist. + +Embedded preservation mirrors `sync-midstream.sh` lines 857–870: scan **all** `dist-dynamic/embedded/*/package.json` under the workspace **before** deleting package directories. + +### 4. Single pass (not sparse-checkout stages) + +`sync-midstream.sh` filtered `plugins-list.yaml` early (lines 691–714) to drive sparse checkout, then scrubbed directories later (886–915). In the overlay workflow the workspace is fully on disk — filter `plugins-list.yaml` and remove directories in **one** module pass. + +### 5. Preserve full `plugins-list.yaml` lines + +Surviving entries are written back with their complete text, including trailing `:` and export CLI arguments (`--embed-package`, `--suppress-native-package`, etc.). + +### 6. Flat-repo path normalization + +Supported-packages entries may use a trailing `/.` for flat repos (e.g. `pagerduty/.`). Normalize by stripping `/.` on both tier-list entries and constructed paths before comparison. No current entries use this, but the bash handles it defensively. + +### 7. Package directory matching + +A directory is kept when its path relative to the workspace: + +- equals a surviving plugins-list path, or +- equals `path/dist-dynamic`, or +- its `package.json` `name` matches an embedded package name + +Scan `package.json` at mindepth 2 (exclude workspace root `package.json`), same as `sync-midstream.sh` line 916. + +### 8. Scope split vs `file-cleanup` + +| Concern | Module | +| ---------------------------------------------------------------------------- | ---------------- | +| Infrastructure dirs, non-supported plugin dirs, filtered `plugins-list.yaml` | `plugin-removal` | +| Test/dev files within surviving packages | `file-cleanup` | + +Infrastructure patterns from bash (lines 878–884): `examples/` (depth 1), `packages/app`, `packages/backend`, `packages/app-next`, `.storybook`, `node_modules`. + +### 9. Out of scope + +- Metadata YAML filtering (`remove-pre-GA-entities.js`) +- `rhdh-community-packages.txt` as scrub input +- `protocol-resolution` / `package-cleanup` (lockfile and package.json rewriting) + +--- + +## Algorithm (implementation contract) + +1. Read `plugins-list.yaml` from `ctx.overlayPath` +2. Read `rhdh-supported-packages.txt` from `ctx.overlayRepoRoot` +3. Workspace name = `path.basename(ctx.overlayPath)` +4. Surviving list = plugins-list entries whose `workspaceName/pluginPath` is in the supported set +5. Collect embedded npm names from all `**/dist-dynamic/embedded/*/package.json` +6. Remove infrastructure directories +7. For each `package.json` at depth ≥ 2: remove parent dir unless kept by list, `dist-dynamic` path, or embedded name +8. Write filtered `plugins-list.yaml` + +## Error handling + +| Condition | Behavior | +| ---------------------------------------------------------- | --------------------------------------------------------------------------------- | +| `rhdh-supported-packages.txt` missing at overlay repo root | Throw | +| `plugins-list.yaml` missing in overlay path | Throw | +| No surviving plugins-list entries | Write empty `plugins-list.yaml`; remove all scannable plugin dirs except embedded | + +## sync-midstream.sh references + +| Behavior | Lines | +| ------------------------------------------------------------ | --------- | +| plugins-list ∩ supported (sparse checkout era) | 691–714 | +| Embedded package collection | 857–870 | +| Infrastructure removal | 878–884 | +| Non-exported plugin removal | 886–915 | +| Community path deletion (repo-wide, **not** replicated here) | 1066–1094 | +| Test/dev removal (**file-cleanup**, not here) | 917–924 | + +## Test fixtures + +Use realistic workspace layouts — see +[source-preparation-design-decisions.md](../../../docs/source-preparation-design-decisions.md) +§12 (fixture workspace layout). + +**For this module specifically:** + +- Exportable plugins under `plugins//` with `plugins/:` in + `plugins-list.yaml` (or `packages/:` when mirroring gitlab-style flat + repos). +- Infrastructure under `packages/app`, `packages/backend`, etc. — not mixed into + `plugins/`. +- Embedded source as a sibling plugin package (e.g. `plugins/embedded-lib/`) whose + `package.json` `name` matches `dist-dynamic/embedded/*/package.json`. +- Post-export state: `plugins//dist-dynamic/` including + `embedded/` when testing preservation. +- Tier list in `input/overlay-root/rhdh-supported-packages.txt` with lines like + `/plugins/` (fixture name = workspace name via + `loadFixture`). diff --git a/prepare-sources/lib/modules/plugin-removal/README.md b/prepare-sources/lib/modules/plugin-removal/README.md new file mode 100644 index 0000000..6540a8e --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/README.md @@ -0,0 +1,98 @@ +# plugin-removal + +Removes plugin source from the workspace that is not needed for building +supported dynamic plugins, and rewrites `plugins-list.yaml` to list only the +surviving supported entries. + +**Pipeline position:** after `generate-manifests`, before `file-cleanup` — see +`modules.ts` for the current ordering. + +## Problem + +After the overlay `export-dynamic` workflow runs, the workspace checkout still +contains the full upstream tree: infrastructure shells (`packages/app`, +`packages/backend`), plugins not exported from this workspace, and plugins not +in the Red Hat supported tier. + +Downstream Konflux builds only need supported plugin source plus any embedded +packages referenced from the initial export's `dist-dynamic/embedded/` output. + +`generate-manifests` must run **before** this module so versions of packages +about to be scrubbed are still on disk for `protocol-resolution`. + +## What the module does + +1. Intersect `plugins-list.yaml` with `rhdh-supported-packages.txt` for this + workspace (`path.basename(ctx.overlayPath)`) +2. Collect embedded package names from all `dist-dynamic/embedded/*/package.json` + files under the workspace +3. Remove infrastructure directories (`examples/`, `packages/app`, + `packages/backend`, `packages/app-next`, `.storybook`, `node_modules`) +4. Remove plugin directories not in the surviving list (unless preserved as an + embedded package, matched by npm `name`) +5. Write filtered `plugins-list.yaml` back to the overlay path (full lines + preserved, including export CLI args) + +Test and dev file removal is **not** done here — see `file-cleanup`. + +## Inputs and outputs + +| Input | Location | +| ------------------- | ------------------------------------------------- | +| Workspace tree | `ctx.workspacePath` | +| Plugins list | `ctx.overlayPath/plugins-list.yaml` | +| Supported tier list | `ctx.overlayRepoRoot/rhdh-supported-packages.txt` | + +| Output | Location | +| --------------------- | ----------------------------------- | +| Scrubbed workspace | `ctx.workspacePath` (in place) | +| Filtered plugins list | `ctx.overlayPath/plugins-list.yaml` | + +## Non-obvious behavior + +**Whitelist, not community blacklist.** Only `rhdh-supported-packages.txt` is +read. Community plugins are removed because they are absent from that list. +`rhdh-community-packages.txt` is used elsewhere (compatibility checks, wiki, +PR labeling) — not here. + +**Embedded packages.** The pipeline starts after the initial export, so +`dist-dynamic/embedded/` already exists. Packages referenced there are kept +even when not in `plugins-list.yaml`, matching `sync-midstream.sh` embedded +preservation logic. + +**`overlayRepoRoot`.** Tier list files live at the overlay repo root, not under +`workspaces//`. The pipeline exposes `ctx.overlayRepoRoot` explicitly +rather than resolving `../..` inside the module. + +**Metadata untouched.** `workspaces/*/metadata/*.yaml` and catalog entities are +not modified. Catalog filtering is a separate concern (`remove-pre-GA-entities.js`). + +## Differences from `sync-midstream.sh` + +| Aspect | `sync-midstream.sh` | This module | +| ----------------- | ---------------------------------------------- | -------------------------------- | +| Checkout | Sparse; early plugins-list filter drives fetch | Full workspace already on disk | +| Pass structure | Filter list, then scrub dirs (separate steps) | Single pass | +| Community removal | Repo-wide blacklist pass | Implicit via supported whitelist | +| Test file removal | Same loop as scrub | `file-cleanup` module | + +Source references: embedded collection and plugin scrubbing in +`sync-midstream.sh` lines 857–915; infrastructure removal lines 878–884. + +## Error conditions + +| Condition | Behavior | +| ---------------------------------------------------------- | ----------------------------------------------------------------------- | +| `rhdh-supported-packages.txt` missing at overlay repo root | Throw | +| `plugins-list.yaml` missing in overlay path | Throw | +| No surviving plugins-list entries | Empty `plugins-list.yaml`; remove scannable plugin dirs except embedded | + +## Tests + +Fixture-based I/O tests under `__fixtures__/`. Each subdirectory name is the +Vitest case title; see the fixture catalog comment in `index.test.ts`. + +Typical workspace layout: exportable plugins under `plugins/`, infrastructure +shells and shared libs under `packages/`. Tier-list files go under +`input/overlay-root/` when needed (fixture directory name = workspace name for +tier-list entries). See `test-utils.ts` for the full fixture convention. diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay-root/rhdh-supported-packages.txt b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay-root/rhdh-supported-packages.txt new file mode 100644 index 0000000..bcbda11 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay-root/rhdh-supported-packages.txt @@ -0,0 +1 @@ +preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/plugins/exported-plugin diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay/plugins-list.yaml b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay/plugins-list.yaml new file mode 100644 index 0000000..7052911 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay/plugins-list.yaml @@ -0,0 +1 @@ +plugins/exported-plugin: --embed-package @example/embedded-lib diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay/source.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/package.json new file mode 100644 index 0000000..00da58d --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/package.json @@ -0,0 +1,5 @@ +{ + "name": "@example/workspace", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/another-lib-source/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/another-lib-source/package.json new file mode 100644 index 0000000..10300fa --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/another-lib-source/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/another-lib", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/embedded-lib-source/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/embedded-lib-source/package.json new file mode 100644 index 0000000..4357afa --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/embedded-lib-source/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/embedded-lib", + "version": "2.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/dist-dynamic/embedded/another-lib/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/dist-dynamic/embedded/another-lib/package.json new file mode 100644 index 0000000..10300fa --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/dist-dynamic/embedded/another-lib/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/another-lib", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/dist-dynamic/embedded/embedded-lib/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/dist-dynamic/embedded/embedded-lib/package.json new file mode 100644 index 0000000..4357afa --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/dist-dynamic/embedded/embedded-lib/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/embedded-lib", + "version": "2.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/package.json new file mode 100644 index 0000000..6824251 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/exported-plugin/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/exported-plugin", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/unrelated-pkg/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/unrelated-pkg/package.json new file mode 100644 index 0000000..6adea9d --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/input/workspace/plugins/unrelated-pkg/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/unrelated-pkg", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/overlay/plugins-list.yaml b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/overlay/plugins-list.yaml new file mode 100644 index 0000000..7052911 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/overlay/plugins-list.yaml @@ -0,0 +1 @@ +plugins/exported-plugin: --embed-package @example/embedded-lib diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/overlay/source.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/package.json new file mode 100644 index 0000000..00da58d --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/package.json @@ -0,0 +1,5 @@ +{ + "name": "@example/workspace", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/another-lib-source/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/another-lib-source/package.json new file mode 100644 index 0000000..10300fa --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/another-lib-source/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/another-lib", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/embedded-lib-source/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/embedded-lib-source/package.json new file mode 100644 index 0000000..4357afa --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/embedded-lib-source/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/embedded-lib", + "version": "2.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/dist-dynamic/embedded/another-lib/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/dist-dynamic/embedded/another-lib/package.json new file mode 100644 index 0000000..10300fa --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/dist-dynamic/embedded/another-lib/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/another-lib", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/dist-dynamic/embedded/embedded-lib/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/dist-dynamic/embedded/embedded-lib/package.json new file mode 100644 index 0000000..4357afa --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/dist-dynamic/embedded/embedded-lib/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/embedded-lib", + "version": "2.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/package.json new file mode 100644 index 0000000..6824251 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin/output/workspace/plugins/exported-plugin/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/exported-plugin", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay-root/rhdh-supported-packages.txt b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay-root/rhdh-supported-packages.txt new file mode 100644 index 0000000..bed37d5 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay-root/rhdh-supported-packages.txt @@ -0,0 +1,4 @@ +# supported plugins for this fixture workspace +preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/plugins/keep-plugin +preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/plugins/keep-with-args +preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/packages/gitlab diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay/plugins-list.yaml b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay/plugins-list.yaml new file mode 100644 index 0000000..8f08e7b --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay/plugins-list.yaml @@ -0,0 +1,8 @@ +#plugins/remove-plugin: not in supported tier +plugins/keep-plugin: +plugins/remove-plugin: +plugins/keep-with-args: --embed-package @example/pkg + +# packages/ prefix paths (gitlab-style flat repo layout) +packages/gitlab: +packages/gitlab-backend: diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay/source.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay/source.json new file mode 100644 index 0000000..fd63efc --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/monorepo", + "repo-ref": "abc123", + "repo-flat": true, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/examples/demo/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/examples/demo/package.json new file mode 100644 index 0000000..4925b07 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/examples/demo/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/demo", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/package.json new file mode 100644 index 0000000..73f89e4 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/package.json @@ -0,0 +1,9 @@ +{ + "name": "@example/workspace", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*" + ] +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/app-next/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/app-next/package.json new file mode 100644 index 0000000..805a734 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/app-next/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/app-next", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/app/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/app/package.json new file mode 100644 index 0000000..1eec1e5 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/app/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/app", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/backend/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/backend/package.json new file mode 100644 index 0000000..93bdfc4 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/backend/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/backend", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/gitlab-backend/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/gitlab-backend/package.json new file mode 100644 index 0000000..d615455 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/gitlab-backend/package.json @@ -0,0 +1,4 @@ +{ + "name": "@immobiliare/backstage-plugin-gitlab-backend", + "version": "6.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/gitlab/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/gitlab/package.json new file mode 100644 index 0000000..3104fa2 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/packages/gitlab/package.json @@ -0,0 +1,4 @@ +{ + "name": "@immobiliare/backstage-plugin-gitlab", + "version": "6.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/.storybook/main.ts b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/.storybook/main.ts new file mode 100644 index 0000000..ff8b4c5 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/.storybook/main.ts @@ -0,0 +1 @@ +export default {}; diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/dist-dynamic/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/dist-dynamic/package.json new file mode 100644 index 0000000..7a4b5db --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/dist-dynamic/package.json @@ -0,0 +1,5 @@ +{ + "name": "@example/keep-plugin", + "version": "1.0.0", + "main": "dist/index.cjs.js" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/package.json new file mode 100644 index 0000000..ff0740c --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-plugin/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/keep-plugin", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-with-args/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-with-args/package.json new file mode 100644 index 0000000..bf98740 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/keep-with-args/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/keep-with-args", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/remove-plugin/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/remove-plugin/package.json new file mode 100644 index 0000000..532fd4a --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/input/workspace/plugins/remove-plugin/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/remove-plugin", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/overlay/plugins-list.yaml b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/overlay/plugins-list.yaml new file mode 100644 index 0000000..072e4c0 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/overlay/plugins-list.yaml @@ -0,0 +1,6 @@ +#plugins/remove-plugin: not in supported tier +plugins/keep-plugin: +plugins/keep-with-args: --embed-package @example/pkg + +# packages/ prefix paths (gitlab-style flat repo layout) +packages/gitlab: diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/overlay/source.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/overlay/source.json new file mode 100644 index 0000000..fd63efc --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/monorepo", + "repo-ref": "abc123", + "repo-flat": true, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/package.json new file mode 100644 index 0000000..73f89e4 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/package.json @@ -0,0 +1,9 @@ +{ + "name": "@example/workspace", + "version": "1.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*" + ] +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/packages/gitlab/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/packages/gitlab/package.json new file mode 100644 index 0000000..3104fa2 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/packages/gitlab/package.json @@ -0,0 +1,4 @@ +{ + "name": "@immobiliare/backstage-plugin-gitlab", + "version": "6.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-plugin/dist-dynamic/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-plugin/dist-dynamic/package.json new file mode 100644 index 0000000..7a4b5db --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-plugin/dist-dynamic/package.json @@ -0,0 +1,5 @@ +{ + "name": "@example/keep-plugin", + "version": "1.0.0", + "main": "dist/index.cjs.js" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-plugin/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-plugin/package.json new file mode 100644 index 0000000..ff0740c --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-plugin/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/keep-plugin", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-with-args/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-with-args/package.json new file mode 100644 index 0000000..bf98740 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list/output/workspace/plugins/keep-with-args/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/keep-with-args", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay-root/rhdh-supported-packages.txt b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay-root/rhdh-supported-packages.txt new file mode 100644 index 0000000..60c6738 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay-root/rhdh-supported-packages.txt @@ -0,0 +1,2 @@ +# no entries match this workspace +other-workspace/plugins/something diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay/plugins-list.yaml b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay/plugins-list.yaml new file mode 100644 index 0000000..11fb04d --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay/plugins-list.yaml @@ -0,0 +1,2 @@ +plugins/alpha: +plugins/beta: --embed-package @scope/lib diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay/source.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/package.json new file mode 100644 index 0000000..00da58d --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/package.json @@ -0,0 +1,5 @@ +{ + "name": "@example/workspace", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/plugins/alpha/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/plugins/alpha/package.json new file mode 100644 index 0000000..72d2fbe --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/plugins/alpha/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/alpha", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/plugins/beta/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/plugins/beta/package.json new file mode 100644 index 0000000..162a4a1 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/input/workspace/plugins/beta/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/beta", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/overlay/plugins-list.yaml b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/overlay/plugins-list.yaml new file mode 100644 index 0000000..e69de29 diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/overlay/source.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/workspace/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/workspace/package.json new file mode 100644 index 0000000..00da58d --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported/output/workspace/package.json @@ -0,0 +1,5 @@ +{ + "name": "@example/workspace", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/error b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/error new file mode 100644 index 0000000..d74797b --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/error @@ -0,0 +1 @@ +plugins-list.yaml not found \ No newline at end of file diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/overlay-root/rhdh-supported-packages.txt b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/overlay-root/rhdh-supported-packages.txt new file mode 100644 index 0000000..8faa355 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/overlay-root/rhdh-supported-packages.txt @@ -0,0 +1 @@ +throws-when-plugins-list-yaml-is-missing/plugins/foo diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/overlay/source.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/overlay/source.json new file mode 100644 index 0000000..eb1806a --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/monorepo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/workspace/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/workspace/package.json new file mode 100644 index 0000000..f30df30 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-plugins-list-yaml-is-missing/input/workspace/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/workspace", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/error b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/error new file mode 100644 index 0000000..8bf2040 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/error @@ -0,0 +1 @@ +rhdh-supported-packages.txt not found \ No newline at end of file diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/overlay/plugins-list.yaml b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/overlay/plugins-list.yaml new file mode 100644 index 0000000..0cfcb48 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/overlay/plugins-list.yaml @@ -0,0 +1 @@ +plugins/foo: diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/overlay/source.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/overlay/source.json new file mode 100644 index 0000000..eb1806a --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/monorepo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/workspace/package.json b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/workspace/package.json new file mode 100644 index 0000000..f30df30 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/__fixtures__/throws-when-rhdh-supported-packages-txt-is-missing/input/workspace/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/workspace", + "version": "1.0.0" +} diff --git a/prepare-sources/lib/modules/plugin-removal/index.test.ts b/prepare-sources/lib/modules/plugin-removal/index.test.ts new file mode 100644 index 0000000..5164960 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/index.test.ts @@ -0,0 +1,159 @@ +import fs from "node:fs"; +import path from "node:path"; + +import { describe, expect, it, vi } from "vite-plus/test"; + +import { loadFixture, makeTempDir, testInputOutputExpectations } from "../../test-utils.ts"; +import { + collectEmbeddedPackageNames, + filterPluginsListBySupported, + normalizeWorkspacePath, + parsePluginsListYaml, + parseTierListFile, + removeInfrastructureDirs, + run, + shouldKeepPackageDir, +} from "./index.ts"; + +/** + * Fixture catalog (`__fixtures__//` — name doubles as the Vitest case title): + * + * - `preserves-supported-plugins-removes-infrastructure-and-rewrites-plugins-list` — + * whitelist filter (plugins/ and packages/ paths), infrastructure removal + * (examples/, packages/app, backend, app-next, .storybook, node_modules), + * dist-dynamic/ preserved for supported plugins, comments and blank lines kept in + * plugins-list rewrite, CLI args preserved on surviving entries + * - `preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin` — embedded + * package source kept via dist-dynamic/embedded name match; unrelated plugin removed + * - `removes-all-plugin-dirs-when-no-plugins-list-entries-are-supported` — empty + * surviving list; all plugin dirs removed + * - `throws-when-rhdh-supported-packages-txt-is-missing` — error when tier list absent + * - `throws-when-plugins-list-yaml-is-missing` — error when plugins-list absent + */ +describe("plugin-removal", () => { + testInputOutputExpectations(import.meta.dirname, run); +}); + +describe("parsePluginsListYaml", () => { + it("parses paths and preserves raw lines with CLI args", () => { + const entries = parsePluginsListYaml(` +# comment +plugins/foo: +plugins/bar: --embed-package @scope/pkg +`); + expect(entries).toEqual([ + { rawLine: "plugins/foo:", pluginPath: "plugins/foo" }, + { rawLine: "plugins/bar: --embed-package @scope/pkg", pluginPath: "plugins/bar" }, + ]); + }); + + it("skips lines with spaces in the plugin path", () => { + const entries = parsePluginsListYaml("some random text\nplugins/valid:"); + expect(entries).toEqual([{ rawLine: "plugins/valid:", pluginPath: "plugins/valid" }]); + }); +}); + +describe("filterPluginsListBySupported", () => { + it("keeps only entries present in the supported tier list", () => { + const entries = parsePluginsListYaml("plugins/a:\nplugins/b:"); + const supported = new Set(["ws/plugins/a"]); + expect(filterPluginsListBySupported(entries, "ws", supported).map((e) => e.pluginPath)).toEqual( + ["plugins/a"], + ); + }); +}); + +describe("normalizeWorkspacePath", () => { + it("strips trailing /.", () => { + expect(normalizeWorkspacePath("pagerduty/.")).toBe("pagerduty"); + expect(normalizeWorkspacePath("pagerduty/plugins/foo")).toBe("pagerduty/plugins/foo"); + }); +}); + +describe("parseTierListFile", () => { + it("skips comments and blank lines", () => { + expect(parseTierListFile("# header\n\nws/plugins/a\n")).toEqual(["ws/plugins/a"]); + }); +}); + +describe("removeInfrastructureDirs", () => { + it("skips file matches that are not directories", () => { + using tmp = makeTempDir(); + const packagesDir = path.join(tmp.path, "packages"); + fs.mkdirSync(packagesDir, { recursive: true }); + fs.writeFileSync(path.join(packagesDir, "backend"), "not a directory"); + const log = vi.fn(); + removeInfrastructureDirs(tmp.path, log); + expect(fs.existsSync(path.join(packagesDir, "backend"))).toBe(true); + expect(log).not.toHaveBeenCalled(); + }); +}); + +describe("collectEmbeddedPackageNames", () => { + it("skips malformed package.json in embedded dirs", () => { + using tmp = loadFixture( + import.meta.dirname, + "preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin", + ); + const embeddedDir = path.join( + tmp.ctx.workspacePath, + "plugins/exported-plugin/dist-dynamic/embedded/bad-pkg", + ); + fs.mkdirSync(embeddedDir, { recursive: true }); + fs.writeFileSync(path.join(embeddedDir, "package.json"), "{ broken"); + const names = collectEmbeddedPackageNames(tmp.ctx.workspacePath); + expect(names.has("@example/embedded-lib")).toBe(true); + expect(names.has("@example/another-lib")).toBe(true); + expect(names.size).toBe(2); + }); + + it("skips package.json without a name field", () => { + using tmp = loadFixture( + import.meta.dirname, + "preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin", + ); + const embeddedDir = path.join( + tmp.ctx.workspacePath, + "plugins/exported-plugin/dist-dynamic/embedded/no-name", + ); + fs.mkdirSync(embeddedDir, { recursive: true }); + fs.writeFileSync(path.join(embeddedDir, "package.json"), '{"version": "1.0.0"}'); + const names = collectEmbeddedPackageNames(tmp.ctx.workspacePath); + expect(names.has("@example/embedded-lib")).toBe(true); + expect(names.has("@example/another-lib")).toBe(true); + expect(names.size).toBe(2); + }); +}); + +describe("shouldKeepPackageDir", () => { + it("keeps listed plugin paths, dist-dynamic dirs, and embedded package names", () => { + const fixture = loadFixture( + import.meta.dirname, + "preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin", + ); + const keep = new Set(["plugins/exported-plugin"]); + const embedded = new Set(["@example/embedded-lib"]); + const ws = fixture.ctx.workspacePath; + + expect(shouldKeepPackageDir(`${ws}/plugins/exported-plugin`, ws, keep, embedded)).toBe(true); + expect( + shouldKeepPackageDir(`${ws}/plugins/exported-plugin/dist-dynamic`, ws, keep, embedded), + ).toBe(true); + expect(shouldKeepPackageDir(`${ws}/plugins/embedded-lib-source`, ws, keep, embedded)).toBe( + true, + ); + expect(shouldKeepPackageDir(`${ws}/plugins/remove-me`, ws, keep, embedded)).toBe(false); + }); + + it("returns false when package.json is malformed", () => { + using tmp = loadFixture( + import.meta.dirname, + "preserves-embedded-source-by-npm-name-and-removes-unrelated-plugin", + ); + const ws = tmp.ctx.workspacePath; + const badDir = `${ws}/plugins/bad-json`; + fs.mkdirSync(badDir, { recursive: true }); + fs.writeFileSync(`${badDir}/package.json`, "{ invalid json"); + expect(shouldKeepPackageDir(badDir, ws, new Set(), new Set(["anything"]))).toBe(false); + }); +}); diff --git a/prepare-sources/lib/modules/plugin-removal/index.ts b/prepare-sources/lib/modules/plugin-removal/index.ts new file mode 100644 index 0000000..0914735 --- /dev/null +++ b/prepare-sources/lib/modules/plugin-removal/index.ts @@ -0,0 +1,216 @@ +import fs from "node:fs"; +import path from "node:path"; +import type { ModuleContext } from "../../pipeline.ts"; + +const SUPPORTED_PACKAGES_FILE = "rhdh-supported-packages.txt"; +const PLUGINS_LIST_FILE = "plugins-list.yaml"; + +/** Normalize workspace path entries (strips a trailing `/.` used for flat repos). */ +export function normalizeWorkspacePath(entry: string): string { + return entry.replace(/\/\.$/, ""); +} + +/** Parse non-comment, non-empty lines from a tier list text file. */ +export function parseTierListFile(content: string): string[] { + const entries: string[] = []; + for (const line of content.split(/\r?\n/)) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith("#")) continue; + entries.push(normalizeWorkspacePath(trimmed)); + } + return entries; +} + +export type PluginsListEntry = { + /** Full line as written in plugins-list.yaml (path + optional CLI args). */ + rawLine: string; + /** Plugin path relative to the workspace root (before `:`). */ + pluginPath: string; +}; + +/** + * Parse `plugins-list.yaml` lines. Comment and blank lines are skipped. + * Lines may end with `:` and optional export CLI arguments. + */ +export function parsePluginsListYaml(content: string): PluginsListEntry[] { + const entries: PluginsListEntry[] = []; + for (const line of content.split(/\r?\n/)) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith("#")) continue; + const withoutListMarker = trimmed.replace(/^-\s*/, ""); + const pluginPath = withoutListMarker.split(":")[0]?.trim(); + if (!pluginPath || pluginPath.includes(" ")) continue; + entries.push({ rawLine: line, pluginPath }); + } + return entries; +} + +/** + * Keep plugins-list entries whose `workspace/pluginPath` appears in the supported tier list. + */ +export function filterPluginsListBySupported( + entries: PluginsListEntry[], + workspaceName: string, + supportedPaths: ReadonlySet, +): PluginsListEntry[] { + return entries.filter((entry) => { + const fullPath = normalizeWorkspacePath(`${workspaceName}/${entry.pluginPath}`); + return supportedPaths.has(fullPath); + }); +} + +function readPackageName(filePath: string): string | undefined { + const raw: unknown = JSON.parse(fs.readFileSync(filePath, "utf8")); + if (typeof raw === "object" && raw !== null && "name" in raw && typeof raw.name === "string") { + return raw.name; + } + return undefined; +} + +/** Collect npm package names from dist-dynamic embedded package.json files under the workspace. */ +export function collectEmbeddedPackageNames(workspacePath: string): Set { + const names = new Set(); + const pattern = path.join(workspacePath, "**/dist-dynamic/embedded/*/package.json"); + for (const pkgPath of fs.globSync(pattern)) { + try { + const name = readPackageName(pkgPath); + if (name) names.add(name); + } catch { + // skip malformed package.json — same tolerance as sync-midstream jq + } + } + return names; +} + +/** Discover `package.json` files at least two directory levels below the workspace root. */ +export function findPackageJsonDirs(workspacePath: string): string[] { + const results: string[] = []; + for (const pkgPath of fs.globSync(path.join(workspacePath, "**/package.json"))) { + const rel = path.relative(workspacePath, pkgPath); + const segments = rel.split(path.sep); + if (segments.length < 3) continue; + results.push(path.dirname(pkgPath)); + } + return results.toSorted((a, b) => a.localeCompare(b)); +} + +export function shouldKeepPackageDir( + packageDir: string, + workspacePath: string, + keepPluginPaths: ReadonlySet, + embeddedNames: ReadonlySet, +): boolean { + const relDir = path.relative(workspacePath, packageDir); + for (const keepPath of keepPluginPaths) { + if (relDir === keepPath || relDir === `${keepPath}/dist-dynamic`) { + return true; + } + } + const pkgJson = path.join(packageDir, "package.json"); + if (!fs.existsSync(pkgJson)) return false; + try { + const name = readPackageName(pkgJson); + return name !== undefined && embeddedNames.has(name); + } catch { + return false; + } +} + +/** Remove infrastructure directories not needed for supported plugin builds. */ +export function removeInfrastructureDirs(workspacePath: string, log: (msg: string) => void): void { + const examplesDir = path.join(workspacePath, "examples"); + if (fs.existsSync(examplesDir) && fs.statSync(examplesDir).isDirectory()) { + fs.rmSync(examplesDir, { recursive: true, force: true }); + log("removed examples/"); + } + + const infraPatterns = [ + path.join(workspacePath, "**/packages/backend"), + path.join(workspacePath, "**/packages/app"), + path.join(workspacePath, "**/packages/app-next"), + path.join(workspacePath, "**/.storybook"), + path.join(workspacePath, "**/node_modules"), + ]; + for (const pattern of infraPatterns) { + for (const dir of fs.globSync(pattern)) { + if (!fs.statSync(dir).isDirectory()) continue; + fs.rmSync(dir, { recursive: true, force: true }); + log(`removed ${path.relative(workspacePath, dir)}`); + } + } +} + +/** + * Rewrite `plugins-list.yaml` keeping comments and blank lines intact, + * removing only uncommented plugin entries that didn't survive filtering. + */ +function writePluginsList( + overlayPath: string, + originalContent: string, + surviving: PluginsListEntry[], +): void { + const survivingRawLines = new Set(surviving.map((e) => e.rawLine)); + const outputLines: string[] = []; + for (const line of originalContent.split(/\r?\n/)) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith("#")) { + outputLines.push(line); + continue; + } + if (survivingRawLines.has(line)) { + outputLines.push(line); + } + } + fs.writeFileSync(path.join(overlayPath, PLUGINS_LIST_FILE), outputLines.join("\n")); +} + +/** + * Removes non-supported plugin source from the workspace and rewrites + * `plugins-list.yaml` to list only surviving supported plugins. + */ +export function run(ctx: ModuleContext): Promise { + const workspaceName = path.basename(ctx.overlayPath); + const supportedFile = path.join(ctx.overlayRepoRoot, SUPPORTED_PACKAGES_FILE); + const pluginsListPath = path.join(ctx.overlayPath, PLUGINS_LIST_FILE); + + if (!fs.existsSync(supportedFile)) { + return Promise.reject(new Error(`${SUPPORTED_PACKAGES_FILE} not found at overlay repo root`)); + } + if (!fs.existsSync(pluginsListPath)) { + return Promise.reject(new Error(`${PLUGINS_LIST_FILE} not found in overlay path`)); + } + + const supportedPaths = new Set(parseTierListFile(fs.readFileSync(supportedFile, "utf8"))); + const pluginsListContent = fs.readFileSync(pluginsListPath, "utf8"); + const allListEntries = parsePluginsListYaml(pluginsListContent); + const survivingList = filterPluginsListBySupported(allListEntries, workspaceName, supportedPaths); + + ctx.log( + `plugins-list.yaml: ${survivingList.length}/${allListEntries.length} entries supported for workspace ${workspaceName}`, + ); + + const keepPluginPaths = new Set( + survivingList.map((entry) => normalizeWorkspacePath(entry.pluginPath)), + ); + const embeddedNames = collectEmbeddedPackageNames(ctx.workspacePath); + if (embeddedNames.size > 0) { + ctx.log( + `embedded packages to preserve: ${[...embeddedNames].toSorted((a, b) => a.localeCompare(b)).join(", ")}`, + ); + } + + removeInfrastructureDirs(ctx.workspacePath, ctx.log); + + for (const packageDir of findPackageJsonDirs(ctx.workspacePath)) { + if (shouldKeepPackageDir(packageDir, ctx.workspacePath, keepPluginPaths, embeddedNames)) { + continue; + } + const rel = path.relative(ctx.workspacePath, packageDir); + fs.rmSync(packageDir, { recursive: true, force: true }); + ctx.log(`removed ${rel}`); + } + + writePluginsList(ctx.overlayPath, pluginsListContent, survivingList); + ctx.log(`written filtered ${PLUGINS_LIST_FILE}`); + return Promise.resolve(); +} diff --git a/prepare-sources/lib/pipeline.test.ts b/prepare-sources/lib/pipeline.test.ts index 7872d2b..6bdfd55 100644 --- a/prepare-sources/lib/pipeline.test.ts +++ b/prepare-sources/lib/pipeline.test.ts @@ -14,7 +14,8 @@ import { makeTempDir } from "./test-utils.ts"; const inputs: PipelineInputs = { workspacePath: "/tmp/ws", - overlayPath: "/tmp/overlay", + overlayPath: "/tmp/overlay/workspaces/test", + overlayRepoRoot: "/tmp/overlay", source: { repo: "https://example.com/repo", "repo-ref": "main", @@ -61,6 +62,7 @@ describe("loadPipelineInputs", () => { expect(result.source["repo-ref"]).toBe("abc123"); expect(result.workspacePath).toBe(workspaceDir.path); expect(result.overlayPath).toBe(overlayDir.path); + expect(result.overlayRepoRoot).toBe(path.resolve(overlayDir.path, "../..")); }); it("throws when workspace path does not exist", () => { diff --git a/prepare-sources/lib/pipeline.ts b/prepare-sources/lib/pipeline.ts index c52b689..a78c12a 100644 --- a/prepare-sources/lib/pipeline.ts +++ b/prepare-sources/lib/pipeline.ts @@ -6,6 +6,8 @@ import { readSourceFile, type SourceJson } from "./source.ts"; export interface PipelineInputs { workspacePath: string; overlayPath: string; + /** Overlay repository root (`overlay-repo/`), parent of `workspaces/`. */ + overlayRepoRoot: string; source: SourceJson; } @@ -34,8 +36,9 @@ export function loadPipelineInputs(workspacePath: string, overlayPath: string): } const source = readSourceFile(path.join(resolved.overlayPath, "source.json")); + const overlayRepoRoot = path.resolve(resolved.overlayPath, "../.."); - return { ...resolved, source }; + return { ...resolved, overlayRepoRoot, source }; } export function selectModules( diff --git a/prepare-sources/lib/test-utils.ts b/prepare-sources/lib/test-utils.ts index 99d94b6..8a08a93 100644 --- a/prepare-sources/lib/test-utils.ts +++ b/prepare-sources/lib/test-utils.ts @@ -156,9 +156,9 @@ function dirAssertions(baseDir: string): DirAssertions { * __fixtures__// * ├── root/ → (optional) repo-root files, see below * ├── input/ - * │ ├── workspace/ → copied into a temp workspace dir - * │ └── overlay/ → copied into a temp overlay dir - * │ └── source.json → parsed into ctx.source + * │ ├── workspace/ → temp workspace (use plugins/, packages/, …) + * │ ├── overlay/ → workspace overlay (plugins-list.yaml, source.json) + * │ └── overlay-root/ → (optional) overlay repo root (tier lists, …) * └── output/ * ├── workspace/ → asserted against workspace after run * └── overlay/ → asserted against overlay after run @@ -177,6 +177,20 @@ function dirAssertions(baseDir: string): DirAssertions { * - If `output//` exists → assert it matches that directory. * - If `output//` is absent → assert no changes from `input//`. * + * **Workspace layout:** Prefer realistic monorepo shapes under `input/workspace/`: + * exportable plugins in `plugins//`, non-plugin packages in + * `packages//`, infrastructure shells in `packages/app` (etc.). Match + * `plugins-list.yaml` paths to that layout (`plugins/foo:` for Backstage-style + * workspaces; `packages/foo:` for flat repos such as gitlab). Include + * `dist-dynamic/` under a plugin when the scenario needs post-export state. + * Avoid arbitrary nesting (e.g. `lib/foo/`) unless the test targets that edge case. + * + * **Overlay root:** When `input/overlay-root/` exists (parallel to `root/` for + * the source repo), its contents are copied to a temp overlay repo root and + * `input/overlay/` is placed at `workspaces//` (the fixture + * directory name is the workspace name for tier-list entries like + * `/plugins/foo`). + * * @param testDir Pass `import.meta.dirname` from your test file. * @param name Fixture subdirectory name under the fixtures dir. * @param fixturesDir Subdirectory name containing fixtures (default: `__fixtures__`). @@ -192,7 +206,8 @@ export function loadFixture( } const workspaceDir = makeTempDir(); - const overlayDir = makeTempDir(); + let overlayDir: TempDir; + let overlayRootDir: TempDir | undefined; let workspacePath = workspaceDir.path; let repoRootDir: TempDir | undefined; @@ -201,7 +216,19 @@ export function loadFixture( fs.cpSync(inputWorkspace, workspaceDir.path, { recursive: true }); const inputOverlay = path.join(fixtureDir, "input", "overlay"); - if (fs.existsSync(inputOverlay)) fs.cpSync(inputOverlay, overlayDir.path, { recursive: true }); + const inputOverlayRoot = path.join(fixtureDir, "input", "overlay-root"); + + if (fs.existsSync(inputOverlayRoot)) { + overlayRootDir = makeTempDir(); + fs.cpSync(inputOverlayRoot, overlayRootDir.path, { recursive: true }); + const overlayPath = path.join(overlayRootDir.path, "workspaces", name); + fs.mkdirSync(overlayPath, { recursive: true }); + if (fs.existsSync(inputOverlay)) fs.cpSync(inputOverlay, overlayPath, { recursive: true }); + overlayDir = { path: overlayPath, [Symbol.dispose]() {} }; + } else { + overlayDir = makeTempDir(); + if (fs.existsSync(inputOverlay)) fs.cpSync(inputOverlay, overlayDir.path, { recursive: true }); + } const fixtureRootDir = path.join(fixtureDir, "root"); if (fs.existsSync(fixtureRootDir)) { @@ -218,10 +245,12 @@ export function loadFixture( throw new Error(`fixture ${name} is missing input/overlay/source.json`); } const source = readSourceFile(sourcePath); + const overlayRepoRoot = overlayRootDir?.path ?? path.resolve(overlayDir.path, "../.."); const ctx: ModuleContext = { workspacePath, overlayPath: overlayDir.path, + overlayRepoRoot, source, log: vi.fn(), }; @@ -252,6 +281,7 @@ export function loadFixture( [Symbol.dispose]() { workspaceDir[Symbol.dispose](); repoRootDir?.[Symbol.dispose](); + overlayRootDir?.[Symbol.dispose](); overlayDir[Symbol.dispose](); }, }; From 0e0017d5b0f70a12e7e97bff8612f78a1b05f9b3 Mon Sep 17 00:00:00 2001 From: David Festal Date: Mon, 14 Sep 2026 20:40:28 +0200 Subject: [PATCH 3/4] feat(prepare-rhdh-supported-sources): implement `file-cleanup` pipeline module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove test, mock, and dev-only files from surviving workspace packages: directories `dev/`, `e2e-tests/`, `__tests__/`, `__mocks__/` and files matching `*.test.ts`, `*.test.tsx`, `*.spec.ts`, `*.spec.tsx`, while preserving paths under `node_modules/` and `dist-dynamic/`. Aligns with `sync-midstream.sh` lines 917–924. Add the module implementation, fixture-based tests, fixtures, and README.md; wire the module into the pipeline runner. Exclude `__fixtures__` directories from Vitest discovery in `vite.config.ts`. Assisted-by: Cursor Signed-off-by: David Festal --- prepare-sources/lib/modules.ts | 3 +- .../lib/modules/file-cleanup/README.md | 70 +++++++++++++++++ .../input/overlay/source.json | 6 ++ .../my-plugin/dist-dynamic/embedded.test.ts | 1 + .../my-plugin/src/__tests__/keep-dir.ts | 1 + .../plugins/my-plugin/src/index.test.ts | 1 + .../workspace/plugins/my-plugin/src/index.ts | 1 + .../my-plugin/dist-dynamic/embedded.test.ts | 1 + .../workspace/plugins/my-plugin/src/index.ts | 1 + .../input/overlay/source.json | 6 ++ .../plugins/my-plugin/__mocks__/mock.ts | 1 + .../workspace/plugins/my-plugin/dev/utils.ts | 1 + .../plugins/my-plugin/e2e-tests/spec.ts | 1 + .../my-plugin/src/__tests__/inside.test.ts | 1 + .../plugins/my-plugin/src/__tests__/nested.ts | 1 + .../plugins/my-plugin/src/bar.spec.ts | 1 + .../plugins/my-plugin/src/foo.spec.tsx | 1 + .../plugins/my-plugin/src/foo.test.tsx | 1 + .../plugins/my-plugin/src/index.mock.ts | 1 + .../plugins/my-plugin/src/index.test.ts | 1 + .../workspace/plugins/my-plugin/src/index.ts | 1 + .../my-plugin/src/stories/Button.stories.tsx | 1 + .../plugins/my-plugin/src/index.mock.ts | 1 + .../workspace/plugins/my-plugin/src/index.ts | 1 + .../my-plugin/src/stories/Button.stories.tsx | 1 + .../lib/modules/file-cleanup/index.test.ts | 18 +++++ .../lib/modules/file-cleanup/index.ts | 78 +++++++++++++++++++ prepare-sources/vite.config.ts | 2 + 28 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 prepare-sources/lib/modules/file-cleanup/README.md create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/dist-dynamic/embedded.test.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/__tests__/keep-dir.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/index.test.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/index.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/output/workspace/plugins/my-plugin/dist-dynamic/embedded.test.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/output/workspace/plugins/my-plugin/src/index.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/__mocks__/mock.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/dev/utils.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/e2e-tests/spec.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/__tests__/inside.test.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/__tests__/nested.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/bar.spec.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/foo.spec.tsx create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/foo.test.tsx create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.mock.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.test.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/stories/Button.stories.tsx create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/index.mock.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/index.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/stories/Button.stories.tsx create mode 100644 prepare-sources/lib/modules/file-cleanup/index.test.ts create mode 100644 prepare-sources/lib/modules/file-cleanup/index.ts diff --git a/prepare-sources/lib/modules.ts b/prepare-sources/lib/modules.ts index bfd37a1..361477f 100644 --- a/prepare-sources/lib/modules.ts +++ b/prepare-sources/lib/modules.ts @@ -3,6 +3,7 @@ import { run as hermeticPrep } from "./modules/hermetic-prep/index.ts"; import { run as makeSelfContained } from "./modules/make-self-contained/index.ts"; import { run as generateManifests } from "./modules/generate-manifests/index.ts"; import { run as pluginRemoval } from "./modules/plugin-removal/index.ts"; +import { run as fileCleanup } from "./modules/file-cleanup/index.ts"; async function notImplemented(ctx: ModuleContext): Promise { ctx.log("not yet implemented"); @@ -14,7 +15,7 @@ export const MODULES: readonly PipelineModule[] = [ { name: "make-self-contained", run: makeSelfContained }, { name: "generate-manifests", run: generateManifests }, { name: "plugin-removal", run: pluginRemoval }, - { name: "file-cleanup", run: notImplemented }, + { name: "file-cleanup", run: fileCleanup }, { name: "protocol-resolution", run: notImplemented }, { name: "package-cleanup", run: notImplemented }, { name: "hermetic-prep", run: hermeticPrep }, diff --git a/prepare-sources/lib/modules/file-cleanup/README.md b/prepare-sources/lib/modules/file-cleanup/README.md new file mode 100644 index 0000000..a8006bb --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/README.md @@ -0,0 +1,70 @@ +# file-cleanup + +Removes test, mock, and dev-only files from surviving workspace packages after +`plugin-removal`. Reduces source size and avoids TypeScript errors from test +files that reference devDependencies removed during scrubbing. + +**Pipeline position:** after `plugin-removal`, before `protocol-resolution` — +see `modules.ts` for the current ordering. + +## Problem + +Surviving plugin directories still contain test specs, mock directories, and +local dev utilities. Downstream Konflux builds do not run tests; these files +only add noise and can fail `tsc` when they import types from scrubbed packages +(for example `@types/jest`). + +## What the module does + +Recursively scans `ctx.workspacePath` and removes: + +| Kind | Patterns | +| ------------------------- | ---------------------------------------------------- | +| Directories (entire tree) | `dev/`, `e2e-tests/`, `__tests__/`, `__mocks__/` | +| Files | `*.test.ts`, `*.test.tsx`, `*.spec.ts`, `*.spec.tsx` | + +Paths under `node_modules/` or `dist-dynamic/` are never touched. + +## Inputs and outputs + +| Input | Location | +| ------------------ | ------------------- | +| Scrubbed workspace | `ctx.workspacePath` | + +| Output | Location | +| ----------------- | ------------------------------ | +| Cleaned workspace | `ctx.workspacePath` (in place) | + +No overlay files are read or written. + +## Non-obvious behavior + +**Full workspace scan.** The bash original searches the entire workspace tree +(`$folder_name`), not only `plugins/`. This module does the same — a stray +`packages/shared/src/foo.test.ts` is removed too. + +**Directory before file.** Removable directories are deleted deepest-first so +nested content is not processed twice. + +**dist-dynamic is preserved.** Test files inside `dist-dynamic/` are kept +because the downstream export step may reference lockfile metadata there; bash +explicitly excludes `*/dist-dynamic/*`. + +## Differences from design-decisions summary + +The pipeline table mentions `*.stories.*` and `*.mock.*`; the legacy +`sync-midstream.sh` `find` command does not remove those. This module follows +the bash script (lines 917–924), not the broader table. + +## Error conditions + +This module does not throw for missing paths. An empty workspace is a no-op. + +## Tests + +Fixture-based I/O tests under `__fixtures__/`. Each subdirectory name is the +Vitest case title; see the fixture catalog comment in `index.test.ts`. + +Typical layout: surviving plugin under `plugins//` with production +source, test dirs, and spec files. Include `dist-dynamic/` and `node_modules/` +subtrees when testing exclusion boundaries. diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/overlay/source.json b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/dist-dynamic/embedded.test.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/dist-dynamic/embedded.test.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/dist-dynamic/embedded.test.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/__tests__/keep-dir.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/__tests__/keep-dir.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/__tests__/keep-dir.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/index.test.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/index.test.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/index.test.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/index.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/index.ts new file mode 100644 index 0000000..0de78a8 --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/input/workspace/plugins/my-plugin/src/index.ts @@ -0,0 +1 @@ +export const plugin = "production"; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/output/workspace/plugins/my-plugin/dist-dynamic/embedded.test.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/output/workspace/plugins/my-plugin/dist-dynamic/embedded.test.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/output/workspace/plugins/my-plugin/dist-dynamic/embedded.test.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/output/workspace/plugins/my-plugin/src/index.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/output/workspace/plugins/my-plugin/src/index.ts new file mode 100644 index 0000000..0de78a8 --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/preserves-files-under-dist-dynamic-and-node-modules/output/workspace/plugins/my-plugin/src/index.ts @@ -0,0 +1 @@ +export const plugin = "production"; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/overlay/source.json b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/__mocks__/mock.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/__mocks__/mock.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/__mocks__/mock.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/dev/utils.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/dev/utils.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/dev/utils.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/e2e-tests/spec.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/e2e-tests/spec.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/e2e-tests/spec.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/__tests__/inside.test.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/__tests__/inside.test.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/__tests__/inside.test.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/__tests__/nested.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/__tests__/nested.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/__tests__/nested.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/bar.spec.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/bar.spec.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/bar.spec.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/foo.spec.tsx b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/foo.spec.tsx new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/foo.spec.tsx @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/foo.test.tsx b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/foo.test.tsx new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/foo.test.tsx @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.mock.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.mock.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.mock.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.test.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.test.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.test.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.ts new file mode 100644 index 0000000..0de78a8 --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/index.ts @@ -0,0 +1 @@ +export const plugin = "production"; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/stories/Button.stories.tsx b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/stories/Button.stories.tsx new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/input/workspace/plugins/my-plugin/src/stories/Button.stories.tsx @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/index.mock.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/index.mock.ts new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/index.mock.ts @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/index.ts b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/index.ts new file mode 100644 index 0000000..0de78a8 --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/index.ts @@ -0,0 +1 @@ +export const plugin = "production"; diff --git a/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/stories/Button.stories.tsx b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/stories/Button.stories.tsx new file mode 100644 index 0000000..1bda49b --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/__fixtures__/removes-test-and-dev-files-from-surviving-plugins/output/workspace/plugins/my-plugin/src/stories/Button.stories.tsx @@ -0,0 +1 @@ +export const placeholder = true; diff --git a/prepare-sources/lib/modules/file-cleanup/index.test.ts b/prepare-sources/lib/modules/file-cleanup/index.test.ts new file mode 100644 index 0000000..7e96734 --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/index.test.ts @@ -0,0 +1,18 @@ +import { describe } from "vite-plus/test"; + +import { testInputOutputExpectations } from "../../test-utils.ts"; +import { run } from "./index.ts"; + +/** + * Fixture catalog (`__fixtures__//` — name doubles as the Vitest case title): + * + * - `removes-test-and-dev-files-from-surviving-plugins` — all removable dir names + * (`dev/`, `e2e-tests/`, `__tests__/`, `__mocks__/`), all test/spec file patterns + * (`*.test.ts`, `*.test.tsx`, `*.spec.ts`, `*.spec.tsx`); production source, + * stories, and `*.mock.ts` kept + * - `preserves-files-under-dist-dynamic-and-node-modules` — exclusion boundaries + * for dist-dynamic/ and node_modules/ + */ +describe("file-cleanup", () => { + testInputOutputExpectations(import.meta.dirname, run); +}); diff --git a/prepare-sources/lib/modules/file-cleanup/index.ts b/prepare-sources/lib/modules/file-cleanup/index.ts new file mode 100644 index 0000000..77fc78c --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/index.ts @@ -0,0 +1,78 @@ +import fs from "node:fs"; +import path from "node:path"; +import type { ModuleContext } from "../../pipeline.ts"; + +/** Directory basenames removed wholesale (sync-midstream.sh find -type d). */ +export const REMOVABLE_DIR_NAMES = new Set(["dev", "e2e-tests", "__tests__", "__mocks__"]); + +const TEST_FILE_PATTERNS = [/\.test\.ts$/, /\.test\.tsx$/, /\.spec\.ts$/, /\.spec\.tsx$/]; + +/** True when a relative workspace path is under node_modules or dist-dynamic. */ +export function isExcludedPath(relativePath: string): boolean { + const normalized = relativePath.split(path.sep).join("/"); + return normalized.includes("/node_modules/") || normalized.includes("/dist-dynamic/"); +} + +export function shouldRemoveDir(dirName: string): boolean { + return REMOVABLE_DIR_NAMES.has(dirName); +} + +export function shouldRemoveFile(fileName: string): boolean { + return TEST_FILE_PATTERNS.some((pattern) => pattern.test(fileName)); +} + +function walkEntries(dir: string): string[] { + const results: string[] = []; + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const fullPath = path.join(dir, entry.name); + results.push(fullPath); + if (entry.isDirectory()) { + results.push(...walkEntries(fullPath)); + } + } + return results; +} + +export function findRemovablePaths(workspacePath: string): { dirs: string[]; files: string[] } { + const dirs: string[] = []; + const files: string[] = []; + + for (const entryPath of walkEntries(workspacePath)) { + const rel = path.relative(workspacePath, entryPath); + if (isExcludedPath(rel)) continue; + + const stat = fs.statSync(entryPath); + const baseName = path.basename(entryPath); + + if (stat.isDirectory() && shouldRemoveDir(baseName)) { + dirs.push(entryPath); + } else if (stat.isFile() && shouldRemoveFile(baseName)) { + files.push(entryPath); + } + } + + dirs.sort((a, b) => b.length - a.length); + return { dirs, files }; +} + +/** + * Removes test, mock, and dev-only files from surviving workspace packages. + * Matches sync-midstream.sh lines 917–924. + */ +export function run(ctx: ModuleContext): Promise { + const { dirs, files } = findRemovablePaths(ctx.workspacePath); + + for (const dir of dirs) { + fs.rmSync(dir, { recursive: true, force: true }); + ctx.log(`removed ${path.relative(ctx.workspacePath, dir)}/`); + } + + for (const file of files) { + // Files under removed dirs were already deleted with their parent. + if (!fs.existsSync(file)) continue; + fs.rmSync(file, { force: true }); + ctx.log(`removed ${path.relative(ctx.workspacePath, file)}`); + } + + return Promise.resolve(); +} diff --git a/prepare-sources/vite.config.ts b/prepare-sources/vite.config.ts index 1465332..db9ae56 100644 --- a/prepare-sources/vite.config.ts +++ b/prepare-sources/vite.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from "vite-plus"; export default defineConfig({ lint: { + ignorePatterns: ["**/__fixtures__/**"], categories: { correctness: "error", suspicious: "error", @@ -24,5 +25,6 @@ export default defineConfig({ 100: true, }, }, + exclude: ["**/node_modules/**", "**/__fixtures__/**"], }, }); From c23367e31836bc0b0cb8f70d1426b966e505250a Mon Sep 17 00:00:00 2001 From: David Festal Date: Wed, 23 Sep 2026 15:28:45 +0200 Subject: [PATCH 4/4] feat(prepare-rhdh-supported-sources): implement `protocol-resolution` pipeline module Resolve `workspace:^` and `backstage:^` protocol references to concrete npm semver ranges in `package.json` and `yarn.lock`. Preserve `workspace:^` for packages that still exist locally on disk, and create `packages/type-shims` when surviving code needs types from scrubbed packages. Add shared `yarn-lock-helpers` for mutating parsed Yarn Berry lockfiles, consumed by `protocol-resolution` and future modules. Add the module implementation, fixture-based tests, fixtures, and README.md; wire the module into the pipeline runner. Assisted-by: Cursor Signed-off-by: David Festal --- .../coverage-tmp/coverage-final.json | 3765 +++++++++++++++++ prepare-sources/lib/modules.ts | 3 +- .../lib/modules/file-cleanup/DESIGN.md | 52 + .../lib/modules/protocol-resolution/DESIGN.md | 82 + .../lib/modules/protocol-resolution/README.md | 64 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 22 + .../input/workspace/package.json | 8 + .../workspace/plugins/consumer/package.json | 8 + .../workspace/plugins/shared/package.json | 5 + .../input/workspace/yarn.lock | 16 + .../output/workspace/manifest.json | 22 + .../output/workspace/package.json | 8 + .../workspace/plugins/consumer/package.json | 8 + .../workspace/plugins/shared/package.json | 5 + .../output/workspace/yarn.lock | 30 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 40 + .../input/workspace/package.json | 6 + .../workspace/packages/my-lib/package.json | 7 + .../workspace/plugins/plugin/package.json | 8 + .../input/workspace/yarn.lock | 33 + .../output/workspace/manifest.json | 40 + .../output/workspace/package.json | 6 + .../workspace/packages/my-lib/package.json | 7 + .../workspace/plugins/plugin/package.json | 8 + .../output/workspace/yarn.lock | 50 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 29 + .../input/workspace/package.json | 9 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 3 + .../input/workspace/tsconfig.json | 6 + .../input/workspace/yarn.lock | 15 + .../output/workspace/manifest.json | 29 + .../output/workspace/package.json | 10 + .../packages/type-shims/package.json | 12 + .../packages/type-shims/tsconfig.json | 9 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 3 + .../output/workspace/tsconfig.json | 10 + .../output/workspace/yarn.lock | 34 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 29 + .../input/workspace/package.json | 9 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 4 + .../input/workspace/tsconfig.json | 6 + .../input/workspace/yarn.lock | 15 + .../output/workspace/manifest.json | 29 + .../output/workspace/package.json | 10 + .../packages/type-shims/package.json | 12 + .../type-shims/src/global-augments.d.ts | 1 + .../packages/type-shims/tsconfig.json | 9 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 4 + .../output/workspace/tsconfig.json | 10 + .../output/workspace/yarn.lock | 34 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 30 + .../input/workspace/package.json | 9 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 3 + .../input/workspace/tsconfig.json | 6 + .../input/workspace/yarn.lock | 15 + .../output/workspace/manifest.json | 30 + .../output/workspace/package.json | 10 + .../packages/type-shims/package.json | 13 + .../type-shims/src/global-augments.d.ts | 1 + .../packages/type-shims/tsconfig.json | 9 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 3 + .../output/workspace/tsconfig.json | 10 + .../output/workspace/yarn.lock | 35 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 29 + .../input/workspace/package.json | 9 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 9 + .../input/workspace/tsconfig.json | 6 + .../input/workspace/yarn.lock | 15 + .../output/workspace/manifest.json | 29 + .../output/workspace/package.json | 10 + .../packages/type-shims/package.json | 12 + .../type-shims/src/global-augments.d.ts | 1 + .../packages/type-shims/tsconfig.json | 9 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 9 + .../output/workspace/tsconfig.json | 10 + .../output/workspace/yarn.lock | 34 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 29 + .../input/workspace/package.json | 11 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 3 + .../input/workspace/tsconfig.json | 6 + .../input/workspace/yarn.lock | 15 + .../output/workspace/manifest.json | 29 + .../output/workspace/package.json | 12 + .../packages/type-shims/package.json | 12 + .../packages/type-shims/tsconfig.json | 9 + .../workspace/plugins/frontend/package.json | 8 + .../workspace/plugins/frontend/src/index.tsx | 3 + .../output/workspace/tsconfig.json | 10 + .../output/workspace/yarn.lock | 34 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 20 + .../input/workspace/package.json | 9 + .../workspace/plugins/plugin/package.json | 5 + .../input/workspace/yarn.lock | 20 + .../output/workspace/manifest.json | 20 + .../output/workspace/package.json | 9 + .../workspace/plugins/plugin/package.json | 5 + .../output/workspace/yarn.lock | 14 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 17 + .../input/workspace/package.json | 6 + .../workspace/plugins/plugin/package.json | 7 + .../input/workspace/yarn.lock | 22 + .../output/workspace/manifest.json | 17 + .../output/workspace/package.json | 6 + .../workspace/plugins/plugin/package.json | 7 + .../output/workspace/yarn.lock | 30 + .../input/overlay/source.json | 1 + .../input/workspace/manifest.json | 22 + .../input/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../input/workspace/yarn.lock | 16 + .../npm-responses/scrubbed-lib@2.0.0.json | 7 + .../output/workspace/manifest.json | 22 + .../output/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../output/workspace/yarn.lock | 26 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 17 + .../input/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../input/workspace/yarn.lock | 15 + .../output/workspace/manifest.json | 17 + .../output/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../output/workspace/yarn.lock | 23 + .../input/overlay/source.json | 6 + .../input/workspace/backstage-manifest.json | 12 + .../input/workspace/manifest.json | 31 + .../input/workspace/package.json | 8 + .../input/workspace/plugins/foo/package.json | 9 + .../workspace/plugins/shared/package.json | 5 + .../input/workspace/yarn.lock | 23 + .../output/workspace/backstage-manifest.json | 12 + .../output/workspace/manifest.json | 31 + .../output/workspace/package.json | 8 + .../output/workspace/plugins/foo/package.json | 9 + .../workspace/plugins/shared/package.json | 5 + .../output/workspace/yarn.lock | 40 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 18 + .../input/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 9 + .../input/workspace/yarn.lock | 16 + .../output/workspace/manifest.json | 18 + .../output/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../output/workspace/yarn.lock | 24 + .../input/overlay/source.json | 6 + .../input/workspace/backstage-manifest.json | 17 + .../input/workspace/backstage.json | 3 + .../input/workspace/manifest.json | 31 + .../input/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../input/workspace/yarn.lock | 24 + .../output/workspace/backstage-manifest.json | 17 + .../output/workspace/backstage.json | 3 + .../output/workspace/manifest.json | 31 + .../output/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../output/workspace/yarn.lock | 32 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 23 + .../input/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../input/workspace/yarn.lock | 22 + .../output/workspace/manifest.json | 23 + .../output/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../output/workspace/yarn.lock | 36 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 32 + .../input/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 11 + .../input/workspace/yarn.lock | 24 + .../output/workspace/manifest.json | 32 + .../output/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 11 + .../output/workspace/yarn.lock | 32 + .../input/overlay/source.json | 1 + .../input/workspace/manifest.json | 23 + .../input/workspace/package.json | 11 + .../workspace/plugins/plugin/package.json | 8 + .../input/workspace/yarn.lock | 10 + .../output/workspace/manifest.json | 23 + .../output/workspace/package.json | 11 + .../workspace/plugins/plugin/package.json | 8 + .../output/workspace/yarn.lock | 24 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 29 + .../input/workspace/package.json | 8 + .../workspace/plugins/consumer/package.json | 9 + .../workspace/plugins/shared/package.json | 5 + .../input/workspace/yarn.lock | 23 + .../output/workspace/manifest.json | 29 + .../output/workspace/package.json | 8 + .../workspace/plugins/consumer/package.json | 9 + .../workspace/plugins/shared/package.json | 5 + .../output/workspace/yarn.lock | 38 + .../input/overlay/source.json | 1 + .../input/workspace/manifest.json | 29 + .../input/workspace/package.json | 8 + .../workspace/plugins/consumer/package.json | 9 + .../workspace/plugins/shared/package.json | 5 + .../input/workspace/yarn.lock | 23 + .../output/workspace/manifest.json | 29 + .../output/workspace/package.json | 8 + .../workspace/plugins/consumer/package.json | 9 + .../workspace/plugins/shared/package.json | 5 + .../output/workspace/yarn.lock | 38 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 17 + .../input/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../input/workspace/yarn.lock | 8 + .../output/workspace/manifest.json | 17 + .../output/workspace/package.json | 8 + .../workspace/plugins/plugin/package.json | 8 + .../output/workspace/yarn.lock | 16 + .../throws-when-manifest-missing/error | 1 + .../input/overlay/source.json | 6 + .../input/workspace/package.json | 5 + .../throws-when-yarn-lock-missing/error | 1 + .../input/overlay/source.json | 6 + .../input/workspace/manifest.json | 9 + .../input/workspace/package.json | 5 + .../modules/protocol-resolution/constants.ts | 28 + .../modules/protocol-resolution/index.test.ts | 91 + .../lib/modules/protocol-resolution/index.ts | 59 + .../protocol-resolution/npm-metadata.ts | 84 + .../protocol-resolution/package-json.ts | 75 + .../protocol-resolution/semver-range.ts | 42 + .../modules/protocol-resolution/type-shims.ts | 370 ++ .../lib/modules/protocol-resolution/utils.ts | 89 + .../protocol-resolution/version-map.ts | 39 + .../protocol-resolution/yarn-lock-blocks.ts | 294 ++ .../protocol-resolution/yarn-lock-enrich.ts | 84 + .../protocol-resolution/yarn-lock-metadata.ts | 360 ++ .../protocol-resolution/yarn-lock-update.ts | 447 ++ prepare-sources/lib/yarn-lock-helpers.ts | 216 + prepare-sources/tsconfig.json | 4 +- prepare-sources/vite.config.ts | 3 + 258 files changed, 9437 insertions(+), 2 deletions(-) create mode 100644 prepare-sources/coverage-tmp/coverage-final.json create mode 100644 prepare-sources/lib/modules/file-cleanup/DESIGN.md create mode 100644 prepare-sources/lib/modules/protocol-resolution/DESIGN.md create mode 100644 prepare-sources/lib/modules/protocol-resolution/README.md create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/plugins/consumer/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/plugins/shared/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/plugins/consumer/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/plugins/shared/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/packages/my-lib/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/packages/my-lib/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/packages/type-shims/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/packages/type-shims/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/src/global-augments.d.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/src/global-augments.d.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/src/global-augments.d.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/packages/type-shims/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/packages/type-shims/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/plugins/frontend/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/plugins/frontend/src/index.tsx create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/tsconfig.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/npm-responses/scrubbed-lib@2.0.0.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/backstage-manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/plugins/foo/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/plugins/shared/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/backstage-manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/plugins/foo/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/plugins/shared/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/backstage-manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/backstage.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/backstage-manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/backstage.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/plugins/consumer/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/plugins/shared/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/plugins/consumer/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/plugins/shared/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/plugins/consumer/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/plugins/shared/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/plugins/consumer/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/plugins/shared/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/plugins/plugin/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/yarn.lock create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/error create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/error create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/overlay/source.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/workspace/manifest.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/workspace/package.json create mode 100644 prepare-sources/lib/modules/protocol-resolution/constants.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/index.test.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/index.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/npm-metadata.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/package-json.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/semver-range.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/type-shims.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/utils.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/version-map.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/yarn-lock-blocks.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/yarn-lock-enrich.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/yarn-lock-metadata.ts create mode 100644 prepare-sources/lib/modules/protocol-resolution/yarn-lock-update.ts create mode 100644 prepare-sources/lib/yarn-lock-helpers.ts diff --git a/prepare-sources/coverage-tmp/coverage-final.json b/prepare-sources/coverage-tmp/coverage-final.json new file mode 100644 index 0000000..9d4b3a9 --- /dev/null +++ b/prepare-sources/coverage-tmp/coverage-final.json @@ -0,0 +1,3765 @@ +{ + "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/cli.ts": { + "path": "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/cli.ts", + "statementMap": { + "0": { "start": { "line": 23, "column": 14 }, "end": { "line": 23, "column": null } }, + "1": { "start": { "line": 35, "column": 21 }, "end": { "line": 47, "column": null } }, + "2": { "start": { "line": 49, "column": 2 }, "end": { "line": 51, "column": null } }, + "3": { "start": { "line": 50, "column": 4 }, "end": { "line": 50, "column": null } }, + "4": { "start": { "line": 53, "column": 2 }, "end": { "line": 55, "column": null } }, + "5": { "start": { "line": 54, "column": 4 }, "end": { "line": 54, "column": null } }, + "6": { "start": { "line": 57, "column": 24 }, "end": { "line": 57, "column": null } }, + "7": { "start": { "line": 58, "column": 22 }, "end": { "line": 58, "column": null } }, + "8": { "start": { "line": 60, "column": 2 }, "end": { "line": 67, "column": null } }, + "9": { "start": { "line": 61, "column": 20 }, "end": { "line": 64, "column": null } }, + "10": { "start": { "line": 65, "column": 17 }, "end": { "line": 65, "column": null } }, + "11": { "start": { "line": 66, "column": 4 }, "end": { "line": 66, "column": null } }, + "12": { "start": { "line": 69, "column": 2 }, "end": { "line": 75, "column": null } }, + "13": { "start": { "line": 79, "column": 15 }, "end": { "line": 79, "column": null } }, + "14": { "start": { "line": 81, "column": 2 }, "end": { "line": 90, "column": null } }, + "15": { "start": { "line": 82, "column": 4 }, "end": { "line": 82, "column": null } }, + "16": { "start": { "line": 83, "column": 9 }, "end": { "line": 90, "column": null } }, + "17": { "start": { "line": 84, "column": 4 }, "end": { "line": 86, "column": null } }, + "18": { "start": { "line": 85, "column": 6 }, "end": { "line": 85, "column": null } }, + "19": { "start": { "line": 88, "column": 19 }, "end": { "line": 88, "column": null } }, + "20": { "start": { "line": 89, "column": 4 }, "end": { "line": 89, "column": null } }, + "21": { "start": { "line": 94, "column": 0 }, "end": { "line": 96, "column": null } } + }, + "fnMap": { + "0": { + "name": "parseArgs", + "decl": { "start": { "line": 34, "column": 16 }, "end": { "line": 34, "column": 26 } }, + "loc": { "start": { "line": 34, "column": 51 }, "end": { "line": 76, "column": null } }, + "line": 34 + }, + "1": { + "name": "main", + "decl": { "start": { "line": 78, "column": 22 }, "end": { "line": 78, "column": 27 } }, + "loc": { "start": { "line": 78, "column": 82 }, "end": { "line": 91, "column": null } }, + "line": 78 + } + }, + "branchMap": { + "0": { + "loc": { "start": { "line": 49, "column": 2 }, "end": { "line": 51, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 49, "column": 2 }, "end": { "line": 51, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 49 + }, + "1": { + "loc": { "start": { "line": 53, "column": 2 }, "end": { "line": 55, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 53, "column": 2 }, "end": { "line": 55, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 53 + }, + "2": { + "loc": { "start": { "line": 60, "column": 2 }, "end": { "line": 67, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 60, "column": 2 }, "end": { "line": 67, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 60 + }, + "3": { + "loc": { "start": { "line": 60, "column": 6 }, "end": { "line": 60, "column": 38 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 60, "column": 6 }, "end": { "line": 60, "column": 24 } }, + { "start": { "line": 60, "column": 24 }, "end": { "line": 60, "column": 38 } } + ], + "line": 60 + }, + "4": { + "loc": { "start": { "line": 62, "column": 10 }, "end": { "line": 62, "column": null } }, + "type": "cond-expr", + "locations": [ + { "start": { "line": 62, "column": 27 }, "end": { "line": 62, "column": 50 } }, + { "start": { "line": 62, "column": 50 }, "end": { "line": 62, "column": null } } + ], + "line": 62 + }, + "5": { + "loc": { "start": { "line": 63, "column": 10 }, "end": { "line": 63, "column": null } }, + "type": "cond-expr", + "locations": [ + { "start": { "line": 63, "column": 25 }, "end": { "line": 63, "column": 46 } }, + { "start": { "line": 63, "column": 46 }, "end": { "line": 63, "column": null } } + ], + "line": 63 + }, + "6": { + "loc": { "start": { "line": 78, "column": 27 }, "end": { "line": 78, "column": 82 } }, + "type": "default-arg", + "locations": [ + { "start": { "line": 78, "column": 44 }, "end": { "line": 78, "column": 82 } } + ], + "line": 78 + }, + "7": { + "loc": { "start": { "line": 81, "column": 2 }, "end": { "line": 90, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 81, "column": 2 }, "end": { "line": 90, "column": null } }, + { "start": { "line": 83, "column": 9 }, "end": { "line": 90, "column": null } } + ], + "line": 81 + }, + "8": { + "loc": { "start": { "line": 83, "column": 9 }, "end": { "line": 90, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 83, "column": 9 }, "end": { "line": 90, "column": null } }, + { "start": { "line": 87, "column": 9 }, "end": { "line": 90, "column": null } } + ], + "line": 83 + } + }, + "s": { + "0": 1, + "1": 13, + "2": 13, + "3": 3, + "4": 9, + "5": 3, + "6": 6, + "7": 6, + "8": 6, + "9": 3, + "10": 3, + "11": 3, + "12": 3, + "13": 3, + "14": 3, + "15": 1, + "16": 2, + "17": 1, + "18": 13, + "19": 1, + "20": 1, + "21": 1 + }, + "f": { "0": 13, "1": 3 }, + "b": { + "0": [3, 10], + "1": [3, 6], + "2": [3, 3], + "3": [6, 4], + "4": [2, 1], + "5": [2, 1], + "6": [3], + "7": [1, 2], + "8": [1, 1] + }, + "meta": { + "lastBranch": 9, + "lastFunction": 2, + "lastStatement": 22, + "seen": { + "s:23:14:23:Infinity": 0, + "f:34:16:34:26": 0, + "s:35:21:47:Infinity": 1, + "b:49:2:51:Infinity:undefined:undefined:undefined:undefined": 0, + "s:49:2:51:Infinity": 2, + "s:50:4:50:Infinity": 3, + "b:53:2:55:Infinity:undefined:undefined:undefined:undefined": 1, + "s:53:2:55:Infinity": 4, + "s:54:4:54:Infinity": 5, + "s:57:24:57:Infinity": 6, + "s:58:22:58:Infinity": 7, + "b:60:2:67:Infinity:undefined:undefined:undefined:undefined": 2, + "s:60:2:67:Infinity": 8, + "b:60:6:60:24:60:24:60:38": 3, + "s:61:20:64:Infinity": 9, + "b:62:27:62:50:62:50:62:Infinity": 4, + "b:63:25:63:46:63:46:63:Infinity": 5, + "s:65:17:65:Infinity": 10, + "s:66:4:66:Infinity": 11, + "s:69:2:75:Infinity": 12, + "f:78:22:78:27": 1, + "b:78:44:78:82": 6, + "s:79:15:79:Infinity": 13, + "b:81:2:90:Infinity:83:9:90:Infinity": 7, + "s:81:2:90:Infinity": 14, + "s:82:4:82:Infinity": 15, + "b:83:9:90:Infinity:87:9:90:Infinity": 8, + "s:83:9:90:Infinity": 16, + "s:84:4:86:Infinity": 17, + "s:85:6:85:Infinity": 18, + "s:88:19:88:Infinity": 19, + "s:89:4:89:Infinity": 20, + "s:94:0:96:Infinity": 21 + }, + "fnNames": {} + } + }, + "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/fs-utils.ts": { + "path": "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/fs-utils.ts", + "statementMap": { + "0": { "start": { "line": 11, "column": 15 }, "end": { "line": 11, "column": null } }, + "1": { "start": { "line": 12, "column": 2 }, "end": { "line": 12, "column": null } } + }, + "fnMap": { + "0": { + "name": "skipExistingFile", + "decl": { "start": { "line": 10, "column": 16 }, "end": { "line": 10, "column": 33 } }, + "loc": { "start": { "line": 10, "column": 69 }, "end": { "line": 13, "column": null } }, + "line": 10 + } + }, + "branchMap": { + "0": { + "loc": { "start": { "line": 12, "column": 9 }, "end": { "line": 12, "column": null } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 12, "column": 9 }, "end": { "line": 12, "column": 31 } }, + { "start": { "line": 12, "column": 31 }, "end": { "line": 12, "column": null } } + ], + "line": 12 + } + }, + "s": { "0": 38, "1": 38 }, + "f": { "0": 38 }, + "b": { "0": [38, 11] }, + "meta": { + "lastBranch": 1, + "lastFunction": 1, + "lastStatement": 2, + "seen": { + "f:10:16:10:33": 0, + "s:11:15:11:Infinity": 0, + "s:12:2:12:Infinity": 1, + "b:12:9:12:31:12:31:12:Infinity": 0 + }, + "fnNames": {} + } + }, + "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/modules.ts": { + "path": "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/modules.ts", + "statementMap": { + "0": { "start": { "line": 7, "column": 2 }, "end": { "line": 7, "column": null } }, + "1": { "start": { "line": 11, "column": 50 }, "end": { "line": 25, "column": null } } + }, + "fnMap": { + "0": { + "name": "notImplemented", + "decl": { "start": { "line": 6, "column": 15 }, "end": { "line": 6, "column": 30 } }, + "loc": { "start": { "line": 6, "column": 65 }, "end": { "line": 8, "column": null } }, + "line": 6 + } + }, + "branchMap": {}, + "s": { "0": 1, "1": 2 }, + "f": { "0": 1 }, + "b": {}, + "meta": { + "lastBranch": 0, + "lastFunction": 1, + "lastStatement": 2, + "seen": { "f:6:15:6:30": 0, "s:7:2:7:Infinity": 0, "s:11:50:25:Infinity": 1 }, + "fnNames": {} + } + }, + "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/pipeline.ts": { + "path": "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/pipeline.ts", + "statementMap": { + "0": { "start": { "line": 23, "column": 19 }, "end": { "line": 26, "column": null } }, + "1": { "start": { "line": 28, "column": 2 }, "end": { "line": 30, "column": null } }, + "2": { "start": { "line": 29, "column": 4 }, "end": { "line": 29, "column": null } }, + "3": { "start": { "line": 32, "column": 2 }, "end": { "line": 34, "column": null } }, + "4": { "start": { "line": 33, "column": 4 }, "end": { "line": 33, "column": null } }, + "5": { "start": { "line": 36, "column": 17 }, "end": { "line": 36, "column": null } }, + "6": { "start": { "line": 38, "column": 2 }, "end": { "line": 38, "column": null } }, + "7": { "start": { "line": 46, "column": 8 }, "end": { "line": 54, "column": null } }, + "8": { "start": { "line": 47, "column": 18 }, "end": { "line": 47, "column": null } }, + "9": { "start": { "line": 47, "column": 43 }, "end": { "line": 47, "column": 58 } }, + "10": { "start": { "line": 48, "column": 4 }, "end": { "line": 52, "column": null } }, + "11": { "start": { "line": 49, "column": 6 }, "end": { "line": 51, "column": null } }, + "12": { "start": { "line": 53, "column": 4 }, "end": { "line": 53, "column": null } }, + "13": { "start": { "line": 56, "column": 16 }, "end": { "line": 56, "column": null } }, + "14": { "start": { "line": 57, "column": 15 }, "end": { "line": 57, "column": null } }, + "15": { "start": { "line": 59, "column": 2 }, "end": { "line": 63, "column": null } }, + "16": { "start": { "line": 60, "column": 4 }, "end": { "line": 62, "column": null } }, + "17": { "start": { "line": 65, "column": 2 }, "end": { "line": 65, "column": null } }, + "18": { "start": { "line": 69, "column": 2 }, "end": { "line": 71, "column": null } }, + "19": { "start": { "line": 70, "column": 4 }, "end": { "line": 70, "column": null } }, + "20": { "start": { "line": 80, "column": 2 }, "end": { "line": 80, "column": null } }, + "21": { "start": { "line": 81, "column": 2 }, "end": { "line": 81, "column": null } }, + "22": { "start": { "line": 82, "column": 2 }, "end": { "line": 82, "column": null } }, + "23": { "start": { "line": 83, "column": 2 }, "end": { "line": 83, "column": null } }, + "24": { "start": { "line": 85, "column": 2 }, "end": { "line": 96, "column": null } }, + "25": { "start": { "line": 86, "column": 16 }, "end": { "line": 86, "column": null } }, + "26": { "start": { "line": 87, "column": 31 }, "end": { "line": 87, "column": null } }, + "27": { "start": { "line": 87, "column": 58 }, "end": { "line": 87, "column": 74 } }, + "28": { "start": { "line": 89, "column": 4 }, "end": { "line": 89, "column": null } }, + "29": { "start": { "line": 90, "column": 4 }, "end": { "line": 94, "column": null } }, + "30": { "start": { "line": 91, "column": 6 }, "end": { "line": 91, "column": null } }, + "31": { "start": { "line": 93, "column": 6 }, "end": { "line": 93, "column": null } }, + "32": { "start": { "line": 95, "column": 4 }, "end": { "line": 95, "column": null } } + }, + "fnMap": { + "0": { + "name": "loadPipelineInputs", + "decl": { "start": { "line": 22, "column": 16 }, "end": { "line": 22, "column": 35 } }, + "loc": { "start": { "line": 22, "column": 95 }, "end": { "line": 39, "column": null } }, + "line": 22 + }, + "1": { + "name": "selectModules", + "decl": { "start": { "line": 41, "column": 16 }, "end": { "line": 41, "column": null } }, + "loc": { "start": { "line": 45, "column": 20 }, "end": { "line": 66, "column": null } }, + "line": 45 + }, + "2": { + "name": "(anonymous_2)", + "decl": { "start": { "line": 46, "column": 8 }, "end": { "line": 46, "column": 19 } }, + "loc": { "start": { "line": 46, "column": 58 }, "end": { "line": 54, "column": null } }, + "line": 46 + }, + "3": { + "name": "(anonymous_3)", + "decl": { "start": { "line": 47, "column": 26 }, "end": { "line": 47, "column": 37 } }, + "loc": { "start": { "line": 47, "column": 43 }, "end": { "line": 47, "column": 58 } }, + "line": 47 + }, + "4": { + "name": "createModuleLog", + "decl": { "start": { "line": 68, "column": 9 }, "end": { "line": 68, "column": 25 } }, + "loc": { "start": { "line": 68, "column": 66 }, "end": { "line": 72, "column": null } }, + "line": 68 + }, + "5": { + "name": "(anonymous_5)", + "decl": { "start": { "line": 69, "column": 2 }, "end": { "line": 69, "column": 10 } }, + "loc": { "start": { "line": 69, "column": 22 }, "end": { "line": 71, "column": null } }, + "line": 69 + }, + "6": { + "name": "runPipeline", + "decl": { "start": { "line": 74, "column": 22 }, "end": { "line": 74, "column": null } }, + "loc": { "start": { "line": 79, "column": 17 }, "end": { "line": 97, "column": null } }, + "line": 79 + }, + "7": { + "name": "(anonymous_7)", + "decl": { "start": { "line": 87, "column": 44 }, "end": { "line": 87, "column": 50 } }, + "loc": { "start": { "line": 87, "column": 58 }, "end": { "line": 87, "column": 74 } }, + "line": 87 + } + }, + "branchMap": { + "0": { + "loc": { "start": { "line": 28, "column": 2 }, "end": { "line": 30, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 28, "column": 2 }, "end": { "line": 30, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 28 + }, + "1": { + "loc": { "start": { "line": 32, "column": 2 }, "end": { "line": 34, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 32, "column": 2 }, "end": { "line": 34, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 32 + }, + "2": { + "loc": { "start": { "line": 48, "column": 4 }, "end": { "line": 52, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 48, "column": 4 }, "end": { "line": 52, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 48 + }, + "3": { + "loc": { "start": { "line": 56, "column": 16 }, "end": { "line": 56, "column": null } }, + "type": "cond-expr", + "locations": [ + { "start": { "line": 56, "column": 42 }, "end": { "line": 56, "column": 79 } }, + { "start": { "line": 56, "column": 79 }, "end": { "line": 56, "column": null } } + ], + "line": 56 + }, + "4": { + "loc": { "start": { "line": 57, "column": 15 }, "end": { "line": 57, "column": null } }, + "type": "cond-expr", + "locations": [ + { "start": { "line": 57, "column": 41 }, "end": { "line": 57, "column": 78 } }, + { "start": { "line": 57, "column": 78 }, "end": { "line": 57, "column": null } } + ], + "line": 57 + }, + "5": { + "loc": { "start": { "line": 59, "column": 2 }, "end": { "line": 63, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 59, "column": 2 }, "end": { "line": 63, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 59 + } + }, + "s": { + "0": 5, + "1": 5, + "2": 1, + "3": 4, + "4": 1, + "5": 3, + "6": 3, + "7": 8, + "8": 7, + "9": 19, + "10": 7, + "11": 1, + "12": 6, + "13": 8, + "14": 8, + "15": 8, + "16": 1, + "17": 6, + "18": 7, + "19": 15, + "20": 4, + "21": 4, + "22": 4, + "23": 4, + "24": 4, + "25": 7, + "26": 7, + "27": 2, + "28": 7, + "29": 7, + "30": 7, + "31": 1, + "32": 6 + }, + "f": { "0": 5, "1": 8, "2": 7, "3": 19, "4": 7, "5": 15, "6": 4, "7": 2 }, + "b": { "0": [1, 4], "1": [1, 3], "2": [1, 6], "3": [4, 4], "4": [3, 4], "5": [1, 7] }, + "meta": { + "lastBranch": 6, + "lastFunction": 8, + "lastStatement": 33, + "seen": { + "f:22:16:22:35": 0, + "s:23:19:26:Infinity": 0, + "b:28:2:30:Infinity:undefined:undefined:undefined:undefined": 0, + "s:28:2:30:Infinity": 1, + "s:29:4:29:Infinity": 2, + "b:32:2:34:Infinity:undefined:undefined:undefined:undefined": 1, + "s:32:2:34:Infinity": 3, + "s:33:4:33:Infinity": 4, + "s:36:17:36:Infinity": 5, + "s:38:2:38:Infinity": 6, + "f:41:16:41:Infinity": 1, + "s:46:8:54:Infinity": 7, + "f:46:8:46:19": 2, + "s:47:18:47:Infinity": 8, + "f:47:26:47:37": 3, + "s:47:43:47:58": 9, + "b:48:4:52:Infinity:undefined:undefined:undefined:undefined": 2, + "s:48:4:52:Infinity": 10, + "s:49:6:51:Infinity": 11, + "s:53:4:53:Infinity": 12, + "s:56:16:56:Infinity": 13, + "b:56:42:56:79:56:79:56:Infinity": 3, + "s:57:15:57:Infinity": 14, + "b:57:41:57:78:57:78:57:Infinity": 4, + "b:59:2:63:Infinity:undefined:undefined:undefined:undefined": 5, + "s:59:2:63:Infinity": 15, + "s:60:4:62:Infinity": 16, + "s:65:2:65:Infinity": 17, + "f:68:9:68:25": 4, + "s:69:2:71:Infinity": 18, + "f:69:2:69:10": 5, + "s:70:4:70:Infinity": 19, + "f:74:22:74:Infinity": 6, + "s:80:2:80:Infinity": 20, + "s:81:2:81:Infinity": 21, + "s:82:2:82:Infinity": 22, + "s:83:2:83:Infinity": 23, + "s:85:2:96:Infinity": 24, + "s:86:16:86:Infinity": 25, + "s:87:31:87:Infinity": 26, + "f:87:44:87:50": 7, + "s:87:58:87:74": 27, + "s:89:4:89:Infinity": 28, + "s:90:4:94:Infinity": 29, + "s:91:6:91:Infinity": 30, + "s:93:6:93:Infinity": 31, + "s:95:4:95:Infinity": 32 + }, + "fnNames": {} + } + }, + "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/source.ts": { + "path": "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/source.ts", + "statementMap": { + "0": { "start": { "line": 27, "column": 2 }, "end": { "line": 27, "column": null } }, + "1": { "start": { "line": 31, "column": 2 }, "end": { "line": 31, "column": null } }, + "2": { "start": { "line": 35, "column": 2 }, "end": { "line": 37, "column": null } }, + "3": { "start": { "line": 36, "column": 4 }, "end": { "line": 36, "column": null } }, + "4": { "start": { "line": 39, "column": 16 }, "end": { "line": 39, "column": null } }, + "5": { "start": { "line": 41, "column": 2 }, "end": { "line": 43, "column": null } }, + "6": { "start": { "line": 42, "column": 4 }, "end": { "line": 42, "column": null } }, + "7": { "start": { "line": 45, "column": 2 }, "end": { "line": 45, "column": null } }, + "8": { "start": { "line": 49, "column": 2 }, "end": { "line": 51, "column": null } }, + "9": { "start": { "line": 50, "column": 4 }, "end": { "line": 50, "column": null } }, + "10": { "start": { "line": 53, "column": 2 }, "end": { "line": 58, "column": null } }, + "11": { "start": { "line": 69, "column": 2 }, "end": { "line": 71, "column": null } }, + "12": { "start": { "line": 70, "column": 4 }, "end": { "line": 70, "column": null } }, + "13": { "start": { "line": 74, "column": 2 }, "end": { "line": 78, "column": null } }, + "14": { "start": { "line": 75, "column": 4 }, "end": { "line": 75, "column": null } }, + "15": { "start": { "line": 77, "column": 4 }, "end": { "line": 77, "column": null } }, + "16": { "start": { "line": 80, "column": 2 }, "end": { "line": 84, "column": null } }, + "17": { "start": { "line": 81, "column": 4 }, "end": { "line": 81, "column": null } }, + "18": { "start": { "line": 83, "column": 4 }, "end": { "line": 83, "column": null } } + }, + "fnMap": { + "0": { + "name": "hasOwn", + "decl": { "start": { "line": 23, "column": 9 }, "end": { "line": 23, "column": null } }, + "loc": { "start": { "line": 26, "column": 33 }, "end": { "line": 28, "column": null } }, + "line": 26 + }, + "1": { + "name": "hasType", + "decl": { "start": { "line": 30, "column": 9 }, "end": { "line": 30, "column": 42 } }, + "loc": { "start": { "line": 30, "column": 92 }, "end": { "line": 32, "column": null } }, + "line": 30 + }, + "2": { + "name": "requireField", + "decl": { "start": { "line": 34, "column": 9 }, "end": { "line": 34, "column": 47 } }, + "loc": { "start": { "line": 34, "column": 98 }, "end": { "line": 46, "column": null } }, + "line": 34 + }, + "3": { + "name": "parseSource", + "decl": { "start": { "line": 48, "column": 9 }, "end": { "line": 48, "column": 21 } }, + "loc": { "start": { "line": 48, "column": 49 }, "end": { "line": 59, "column": null } }, + "line": 48 + }, + "4": { + "name": "readSourceFile", + "decl": { "start": { "line": 68, "column": 16 }, "end": { "line": 68, "column": 31 } }, + "loc": { "start": { "line": 68, "column": 61 }, "end": { "line": 85, "column": null } }, + "line": 68 + } + }, + "branchMap": { + "0": { + "loc": { "start": { "line": 35, "column": 2 }, "end": { "line": 37, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 35, "column": 2 }, "end": { "line": 37, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 35 + }, + "1": { + "loc": { "start": { "line": 41, "column": 2 }, "end": { "line": 43, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 41, "column": 2 }, "end": { "line": 43, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 41 + }, + "2": { + "loc": { "start": { "line": 49, "column": 2 }, "end": { "line": 51, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 49, "column": 2 }, "end": { "line": 51, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 49 + }, + "3": { + "loc": { "start": { "line": 49, "column": 6 }, "end": { "line": 49, "column": 75 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 49, "column": 6 }, "end": { "line": 49, "column": 35 } }, + { "start": { "line": 49, "column": 35 }, "end": { "line": 49, "column": 53 } }, + { "start": { "line": 49, "column": 53 }, "end": { "line": 49, "column": 75 } } + ], + "line": 49 + }, + "4": { + "loc": { "start": { "line": 69, "column": 2 }, "end": { "line": 71, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 69, "column": 2 }, "end": { "line": 71, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 69 + } + }, + "s": { + "0": 194, + "1": 190, + "2": 194, + "3": 4, + "4": 190, + "5": 190, + "6": 2, + "7": 188, + "8": 56, + "9": 5, + "10": 51, + "11": 60, + "12": 2, + "13": 58, + "14": 58, + "15": 2, + "16": 56, + "17": 56, + "18": 11 + }, + "f": { "0": 194, "1": 190, "2": 194, "3": 56, "4": 60 }, + "b": { "0": [4, 190], "1": [2, 188], "2": [5, 51], "3": [56, 53, 52], "4": [2, 58] }, + "meta": { + "lastBranch": 5, + "lastFunction": 5, + "lastStatement": 19, + "seen": { + "f:23:9:23:Infinity": 0, + "s:27:2:27:Infinity": 0, + "f:30:9:30:42": 1, + "s:31:2:31:Infinity": 1, + "f:34:9:34:47": 2, + "b:35:2:37:Infinity:undefined:undefined:undefined:undefined": 0, + "s:35:2:37:Infinity": 2, + "s:36:4:36:Infinity": 3, + "s:39:16:39:Infinity": 4, + "b:41:2:43:Infinity:undefined:undefined:undefined:undefined": 1, + "s:41:2:43:Infinity": 5, + "s:42:4:42:Infinity": 6, + "s:45:2:45:Infinity": 7, + "f:48:9:48:21": 3, + "b:49:2:51:Infinity:undefined:undefined:undefined:undefined": 2, + "s:49:2:51:Infinity": 8, + "b:49:6:49:35:49:35:49:53:49:53:49:75": 3, + "s:50:4:50:Infinity": 9, + "s:53:2:58:Infinity": 10, + "f:68:16:68:31": 4, + "b:69:2:71:Infinity:undefined:undefined:undefined:undefined": 4, + "s:69:2:71:Infinity": 11, + "s:70:4:70:Infinity": 12, + "s:74:2:78:Infinity": 13, + "s:75:4:75:Infinity": 14, + "s:77:4:77:Infinity": 15, + "s:80:2:84:Infinity": 16, + "s:81:4:81:Infinity": 17, + "s:83:4:83:Infinity": 18 + }, + "fnNames": {} + } + }, + "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/yarn-lock-parser.ts": { + "path": "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/yarn-lock-parser.ts", + "statementMap": { + "0": { "start": { "line": 50, "column": 19 }, "end": { "line": 50, "column": null } }, + "1": { "start": { "line": 51, "column": 2 }, "end": { "line": 51, "column": null } }, + "2": { "start": { "line": 51, "column": 23 }, "end": { "line": 51, "column": null } }, + "3": { "start": { "line": 52, "column": 15 }, "end": { "line": 52, "column": null } }, + "4": { "start": { "line": 53, "column": 2 }, "end": { "line": 53, "column": null } }, + "5": { "start": { "line": 53, "column": 25 }, "end": { "line": 53, "column": null } }, + "6": { "start": { "line": 54, "column": 15 }, "end": { "line": 54, "column": null } }, + "7": { "start": { "line": 55, "column": 14 }, "end": { "line": 55, "column": null } }, + "8": { "start": { "line": 56, "column": 2 }, "end": { "line": 56, "column": null } }, + "9": { "start": { "line": 56, "column": 54 }, "end": { "line": 56, "column": null } }, + "10": { "start": { "line": 57, "column": 2 }, "end": { "line": 57, "column": null } }, + "11": { "start": { "line": 66, "column": 19 }, "end": { "line": 66, "column": null } }, + "12": { "start": { "line": 67, "column": 2 }, "end": { "line": 67, "column": null } }, + "13": { "start": { "line": 67, "column": 23 }, "end": { "line": 67, "column": null } }, + "14": { "start": { "line": 68, "column": 15 }, "end": { "line": 68, "column": null } }, + "15": { "start": { "line": 69, "column": 2 }, "end": { "line": 69, "column": null } }, + "16": { "start": { "line": 69, "column": 25 }, "end": { "line": 69, "column": null } }, + "17": { "start": { "line": 70, "column": 15 }, "end": { "line": 70, "column": null } }, + "18": { "start": { "line": 71, "column": 2 }, "end": { "line": 71, "column": null } }, + "19": { "start": { "line": 71, "column": 32 }, "end": { "line": 71, "column": null } }, + "20": { "start": { "line": 72, "column": 2 }, "end": { "line": 72, "column": null } }, + "21": { "start": { "line": 81, "column": 17 }, "end": { "line": 81, "column": null } }, + "22": { "start": { "line": 82, "column": 2 }, "end": { "line": 90, "column": null } }, + "23": { "start": { "line": 83, "column": 17 }, "end": { "line": 83, "column": null } }, + "24": { "start": { "line": 84, "column": 18 }, "end": { "line": 84, "column": null } }, + "25": { "start": { "line": 85, "column": 4 }, "end": { "line": 88, "column": null } }, + "26": { "start": { "line": 86, "column": 18 }, "end": { "line": 86, "column": null } }, + "27": { "start": { "line": 87, "column": 6 }, "end": { "line": 87, "column": null } }, + "28": { "start": { "line": 87, "column": 26 }, "end": { "line": 87, "column": null } }, + "29": { "start": { "line": 89, "column": 4 }, "end": { "line": 89, "column": null } }, + "30": { "start": { "line": 91, "column": 2 }, "end": { "line": 91, "column": null } }, + "31": { "start": { "line": 100, "column": 17 }, "end": { "line": 100, "column": null } }, + "32": { "start": { "line": 101, "column": 2 }, "end": { "line": 108, "column": null } }, + "33": { "start": { "line": 102, "column": 17 }, "end": { "line": 102, "column": null } }, + "34": { "start": { "line": 103, "column": 4 }, "end": { "line": 106, "column": null } }, + "35": { "start": { "line": 104, "column": 18 }, "end": { "line": 104, "column": null } }, + "36": { "start": { "line": 105, "column": 6 }, "end": { "line": 105, "column": null } }, + "37": { "start": { "line": 105, "column": 26 }, "end": { "line": 105, "column": null } }, + "38": { "start": { "line": 107, "column": 4 }, "end": { "line": 107, "column": null } }, + "39": { "start": { "line": 109, "column": 2 }, "end": { "line": 109, "column": null } }, + "40": { "start": { "line": 118, "column": 17 }, "end": { "line": 118, "column": null } }, + "41": { "start": { "line": 119, "column": 2 }, "end": { "line": 127, "column": null } }, + "42": { "start": { "line": 120, "column": 17 }, "end": { "line": 120, "column": null } }, + "43": { "start": { "line": 121, "column": 18 }, "end": { "line": 121, "column": null } }, + "44": { "start": { "line": 122, "column": 4 }, "end": { "line": 125, "column": null } }, + "45": { "start": { "line": 123, "column": 19 }, "end": { "line": 123, "column": null } }, + "46": { "start": { "line": 124, "column": 6 }, "end": { "line": 124, "column": null } }, + "47": { "start": { "line": 124, "column": 27 }, "end": { "line": 124, "column": null } }, + "48": { "start": { "line": 126, "column": 4 }, "end": { "line": 126, "column": null } }, + "49": { "start": { "line": 128, "column": 2 }, "end": { "line": 128, "column": null } }, + "50": { "start": { "line": 138, "column": 2 }, "end": { "line": 138, "column": null } }, + "51": { "start": { "line": 138, "column": 58 }, "end": { "line": 138, "column": null } }, + "52": { "start": { "line": 139, "column": 19 }, "end": { "line": 139, "column": null } }, + "53": { "start": { "line": 140, "column": 2 }, "end": { "line": 140, "column": null } }, + "54": { "start": { "line": 140, "column": 23 }, "end": { "line": 140, "column": null } }, + "55": { "start": { "line": 141, "column": 2 }, "end": { "line": 141, "column": null } }, + "56": { "start": { "line": 156, "column": 16 }, "end": { "line": 156, "column": null } }, + "57": { "start": { "line": 158, "column": 22 }, "end": { "line": 158, "column": null } }, + "58": { "start": { "line": 159, "column": 19 }, "end": { "line": 159, "column": null } }, + "59": { "start": { "line": 161, "column": 21 }, "end": { "line": 161, "column": null } }, + "60": { "start": { "line": 161, "column": 60 }, "end": { "line": 161, "column": 68 } }, + "61": { "start": { "line": 162, "column": 17 }, "end": { "line": 162, "column": null } }, + "62": { "start": { "line": 164, "column": 2 }, "end": { "line": 164, "column": null } }, + "63": { "start": { "line": 172, "column": 10 }, "end": { "line": 172, "column": null } }, + "64": { "start": { "line": 173, "column": 2 }, "end": { "line": 186, "column": null } }, + "65": { "start": { "line": 174, "column": 4 }, "end": { "line": 185, "column": null } }, + "66": { "start": { "line": 175, "column": 6 }, "end": { "line": 175, "column": null } }, + "67": { "start": { "line": 176, "column": 11 }, "end": { "line": 185, "column": null } }, + "68": { "start": { "line": 177, "column": 6 }, "end": { "line": 177, "column": null } }, + "69": { "start": { "line": 178, "column": 6 }, "end": { "line": 181, "column": null } }, + "70": { "start": { "line": 179, "column": 8 }, "end": { "line": 179, "column": null } }, + "71": { "start": { "line": 179, "column": 40 }, "end": { "line": 179, "column": null } }, + "72": { "start": { "line": 180, "column": 8 }, "end": { "line": 180, "column": null } }, + "73": { "start": { "line": 182, "column": 6 }, "end": { "line": 182, "column": null } }, + "74": { "start": { "line": 184, "column": 6 }, "end": { "line": 184, "column": null } }, + "75": { "start": { "line": 187, "column": 2 }, "end": { "line": 187, "column": null } }, + "76": { "start": { "line": 196, "column": 31 }, "end": { "line": 196, "column": null } }, + "77": { "start": { "line": 197, "column": 2 }, "end": { "line": 206, "column": null } }, + "78": { "start": { "line": 198, "column": 4 }, "end": { "line": 205, "column": null } }, + "79": { "start": { "line": 199, "column": 6 }, "end": { "line": 199, "column": null } }, + "80": { "start": { "line": 201, "column": 22 }, "end": { "line": 201, "column": null } }, + "81": { "start": { "line": 202, "column": 6 }, "end": { "line": 204, "column": null } }, + "82": { "start": { "line": 203, "column": 8 }, "end": { "line": 203, "column": null } }, + "83": { "start": { "line": 207, "column": 2 }, "end": { "line": 207, "column": null } }, + "84": { "start": { "line": 211, "column": 22 }, "end": { "line": 211, "column": null } }, + "85": { "start": { "line": 212, "column": 17 }, "end": { "line": 212, "column": null } }, + "86": { "start": { "line": 213, "column": 2 }, "end": { "line": 213, "column": null } }, + "87": { "start": { "line": 217, "column": 18 }, "end": { "line": 217, "column": null } }, + "88": { "start": { "line": 218, "column": 2 }, "end": { "line": 220, "column": null } }, + "89": { "start": { "line": 219, "column": 4 }, "end": { "line": 219, "column": null } }, + "90": { "start": { "line": 221, "column": 2 }, "end": { "line": 221, "column": null } }, + "91": { "start": { "line": 229, "column": 52 }, "end": { "line": 229, "column": null } }, + "92": { "start": { "line": 231, "column": 2 }, "end": { "line": 249, "column": null } }, + "93": { "start": { "line": 232, "column": 19 }, "end": { "line": 232, "column": null } }, + "94": { "start": { "line": 233, "column": 4 }, "end": { "line": 236, "column": null } }, + "95": { "start": { "line": 234, "column": 6 }, "end": { "line": 234, "column": null } }, + "96": { "start": { "line": 235, "column": 6 }, "end": { "line": 235, "column": null } }, + "97": { "start": { "line": 238, "column": 24 }, "end": { "line": 238, "column": null } }, + "98": { "start": { "line": 239, "column": 4 }, "end": { "line": 248, "column": null } }, + "99": { "start": { "line": 240, "column": 23 }, "end": { "line": 242, "column": null } }, + "100": { "start": { "line": 241, "column": 15 }, "end": { "line": 241, "column": null } }, + "101": { "start": { "line": 243, "column": 6 }, "end": { "line": 247, "column": null } }, + "102": { "start": { "line": 244, "column": 8 }, "end": { "line": 244, "column": null } }, + "103": { "start": { "line": 246, "column": 8 }, "end": { "line": 246, "column": null } }, + "104": { "start": { "line": 251, "column": 2 }, "end": { "line": 251, "column": null } }, + "105": { "start": { "line": 260, "column": 31 }, "end": { "line": 260, "column": null } }, + "106": { "start": { "line": 261, "column": 2 }, "end": { "line": 268, "column": null } }, + "107": { "start": { "line": 262, "column": 4 }, "end": { "line": 267, "column": null } }, + "108": { "start": { "line": 263, "column": 6 }, "end": { "line": 263, "column": null } }, + "109": { "start": { "line": 265, "column": 22 }, "end": { "line": 265, "column": null } }, + "110": { "start": { "line": 266, "column": 6 }, "end": { "line": 266, "column": null } }, + "111": { "start": { "line": 266, "column": 19 }, "end": { "line": 266, "column": null } }, + "112": { "start": { "line": 269, "column": 2 }, "end": { "line": 269, "column": null } }, + "113": { "start": { "line": 273, "column": 45 }, "end": { "line": 273, "column": null } }, + "114": { "start": { "line": 274, "column": 2 }, "end": { "line": 280, "column": null } }, + "115": { "start": { "line": 275, "column": 4 }, "end": { "line": 275, "column": null } }, + "116": { "start": { "line": 275, "column": 63 }, "end": { "line": 275, "column": null } }, + "117": { "start": { "line": 276, "column": 15 }, "end": { "line": 276, "column": null } }, + "118": { "start": { "line": 277, "column": 4 }, "end": { "line": 279, "column": null } }, + "119": { "start": { "line": 278, "column": 6 }, "end": { "line": 278, "column": null } }, + "120": { "start": { "line": 281, "column": 2 }, "end": { "line": 281, "column": null } }, + "121": { "start": { "line": 285, "column": 65 }, "end": { "line": 285, "column": null } }, + "122": { "start": { "line": 286, "column": 56 }, "end": { "line": 286, "column": null } }, + "123": { "start": { "line": 288, "column": 2 }, "end": { "line": 306, "column": null } }, + "124": { "start": { "line": 289, "column": 4 }, "end": { "line": 289, "column": null } }, + "125": { "start": { "line": 289, "column": 34 }, "end": { "line": 289, "column": null } }, + "126": { "start": { "line": 291, "column": 4 }, "end": { "line": 299, "column": null } }, + "127": { "start": { "line": 292, "column": 6 }, "end": { "line": 297, "column": null } }, + "128": { "start": { "line": 293, "column": 19 }, "end": { "line": 293, "column": null } }, + "129": { "start": { "line": 294, "column": 8 }, "end": { "line": 296, "column": null } }, + "130": { "start": { "line": 295, "column": 10 }, "end": { "line": 295, "column": null } }, + "131": { "start": { "line": 298, "column": 6 }, "end": { "line": 298, "column": null } }, + "132": { "start": { "line": 301, "column": 16 }, "end": { "line": 301, "column": null } }, + "133": { "start": { "line": 302, "column": 4 }, "end": { "line": 305, "column": null } }, + "134": { "start": { "line": 303, "column": 6 }, "end": { "line": 303, "column": null } }, + "135": { "start": { "line": 304, "column": 6 }, "end": { "line": 304, "column": null } }, + "136": { "start": { "line": 308, "column": 2 }, "end": { "line": 308, "column": null } }, + "137": { "start": { "line": 316, "column": 26 }, "end": { "line": 316, "column": null } }, + "138": { "start": { "line": 318, "column": 2 }, "end": { "line": 320, "column": null } }, + "139": { "start": { "line": 319, "column": 4 }, "end": { "line": 319, "column": null } }, + "140": { "start": { "line": 322, "column": 2 }, "end": { "line": 325, "column": null } }, + "141": { "start": { "line": 323, "column": 4 }, "end": { "line": 323, "column": null } }, + "142": { "start": { "line": 324, "column": 4 }, "end": { "line": 324, "column": null } }, + "143": { "start": { "line": 327, "column": 2 }, "end": { "line": 327, "column": null } }, + "144": { "start": { "line": 331, "column": 25 }, "end": { "line": 331, "column": null } }, + "145": { "start": { "line": 332, "column": 16 }, "end": { "line": 332, "column": null } }, + "146": { "start": { "line": 334, "column": 2 }, "end": { "line": 361, "column": null } }, + "147": { "start": { "line": 335, "column": 4 }, "end": { "line": 360, "column": null } }, + "148": { "start": { "line": 337, "column": 8 }, "end": { "line": 337, "column": null } }, + "149": { "start": { "line": 338, "column": 8 }, "end": { "line": 338, "column": null } }, + "150": { "start": { "line": 340, "column": 8 }, "end": { "line": 340, "column": null } }, + "151": { "start": { "line": 341, "column": 8 }, "end": { "line": 343, "column": null } }, + "152": { "start": { "line": 342, "column": 10 }, "end": { "line": 342, "column": null } }, + "153": { "start": { "line": 344, "column": 8 }, "end": { "line": 344, "column": null } }, + "154": { "start": { "line": 346, "column": 8 }, "end": { "line": 346, "column": null } }, + "155": { "start": { "line": 347, "column": 8 }, "end": { "line": 352, "column": null } }, + "156": { "start": { "line": 348, "column": 10 }, "end": { "line": 348, "column": null } }, + "157": { "start": { "line": 349, "column": 10 }, "end": { "line": 351, "column": null } }, + "158": { "start": { "line": 350, "column": 12 }, "end": { "line": 350, "column": null } }, + "159": { "start": { "line": 353, "column": 8 }, "end": { "line": 353, "column": null } }, + "160": { "start": { "line": 363, "column": 2 }, "end": { "line": 363, "column": null } }, + "161": { "start": { "line": 371, "column": 16 }, "end": { "line": 371, "column": null } }, + "162": { "start": { "line": 372, "column": 2 }, "end": { "line": 372, "column": null } }, + "163": { "start": { "line": 372, "column": 41 }, "end": { "line": 372, "column": null } }, + "164": { "start": { "line": 373, "column": 2 }, "end": { "line": 373, "column": null } }, + "165": { "start": { "line": 380, "column": 16 }, "end": { "line": 380, "column": null } }, + "166": { "start": { "line": 381, "column": 2 }, "end": { "line": 381, "column": null } }, + "167": { "start": { "line": 381, "column": 38 }, "end": { "line": 381, "column": null } }, + "168": { "start": { "line": 382, "column": 2 }, "end": { "line": 382, "column": null } }, + "169": { "start": { "line": 389, "column": 16 }, "end": { "line": 389, "column": null } }, + "170": { "start": { "line": 390, "column": 2 }, "end": { "line": 390, "column": null } }, + "171": { "start": { "line": 390, "column": 45 }, "end": { "line": 390, "column": null } }, + "172": { "start": { "line": 391, "column": 2 }, "end": { "line": 391, "column": null } } + }, + "fnMap": { + "0": { + "name": "matchScalar", + "decl": { "start": { "line": 49, "column": 9 }, "end": { "line": 49, "column": 21 } }, + "loc": { "start": { "line": 49, "column": 73 }, "end": { "line": 58, "column": null } }, + "line": 49 + }, + "1": { + "name": "matchSectionHeader", + "decl": { "start": { "line": 65, "column": 9 }, "end": { "line": 65, "column": 28 } }, + "loc": { "start": { "line": 65, "column": 57 }, "end": { "line": 73, "column": null } }, + "line": 65 + }, + "2": { + "name": "matchMapEntry", + "decl": { "start": { "line": 80, "column": 9 }, "end": { "line": 80, "column": 23 } }, + "loc": { "start": { "line": 80, "column": 74 }, "end": { "line": 92, "column": null } }, + "line": 80 + }, + "3": { + "name": "matchNestedKey", + "decl": { "start": { "line": 99, "column": 9 }, "end": { "line": 99, "column": 24 } }, + "loc": { "start": { "line": 99, "column": 53 }, "end": { "line": 110, "column": null } }, + "line": 99 + }, + "4": { + "name": "matchNestedProp", + "decl": { "start": { "line": 117, "column": 9 }, "end": { "line": 117, "column": 25 } }, + "loc": { "start": { "line": 117, "column": 77 }, "end": { "line": 129, "column": null } }, + "line": 117 + }, + "5": { + "name": "isNestedMapHeader", + "decl": { "start": { "line": 137, "column": 9 }, "end": { "line": 137, "column": 27 } }, + "loc": { "start": { "line": 137, "column": 50 }, "end": { "line": 142, "column": null } }, + "line": 137 + }, + "6": { + "name": "parseLockfile", + "decl": { "start": { "line": 155, "column": 16 }, "end": { "line": 155, "column": 30 } }, + "loc": { "start": { "line": 155, "column": 57 }, "end": { "line": 165, "column": null } }, + "line": 155 + }, + "7": { + "name": "(anonymous_7)", + "decl": { "start": { "line": 161, "column": 46 }, "end": { "line": 161, "column": 54 } }, + "loc": { "start": { "line": 161, "column": 60 }, "end": { "line": 161, "column": 68 } }, + "line": 161 + }, + "8": { + "name": "findPreambleEnd", + "decl": { "start": { "line": 171, "column": 9 }, "end": { "line": 171, "column": 25 } }, + "loc": { "start": { "line": 171, "column": 50 }, "end": { "line": 188, "column": null } }, + "line": 171 + }, + "9": { + "name": "splitIntoBlockGroups", + "decl": { "start": { "line": 195, "column": 9 }, "end": { "line": 195, "column": 30 } }, + "loc": { "start": { "line": 195, "column": 61 }, "end": { "line": 208, "column": null } }, + "line": 195 + }, + "10": { + "name": "parseBlockGroup", + "decl": { "start": { "line": 210, "column": 9 }, "end": { "line": 210, "column": 25 } }, + "loc": { "start": { "line": 210, "column": 59 }, "end": { "line": 214, "column": null } }, + "line": 210 + }, + "11": { + "name": "parseDescriptors", + "decl": { "start": { "line": 216, "column": 9 }, "end": { "line": 216, "column": 26 } }, + "loc": { "start": { "line": 216, "column": 49 }, "end": { "line": 222, "column": null } }, + "line": 216 + }, + "12": { + "name": "parseFields", + "decl": { "start": { "line": 228, "column": 9 }, "end": { "line": 228, "column": 21 } }, + "loc": { "start": { "line": 228, "column": 77 }, "end": { "line": 252, "column": null } }, + "line": 228 + }, + "13": { + "name": "(anonymous_13)", + "decl": { "start": { "line": 240, "column": 32 }, "end": { "line": 240, "column": null } }, + "loc": { "start": { "line": 241, "column": 15 }, "end": { "line": 241, "column": null } }, + "line": 241 + }, + "14": { + "name": "groupByField", + "decl": { "start": { "line": 259, "column": 9 }, "end": { "line": 259, "column": 22 } }, + "loc": { "start": { "line": 259, "column": 53 }, "end": { "line": 270, "column": null } }, + "line": 259 + }, + "15": { + "name": "parseMapLines", + "decl": { "start": { "line": 272, "column": 9 }, "end": { "line": 272, "column": 23 } }, + "loc": { "start": { "line": 272, "column": 50 }, "end": { "line": 282, "column": null } }, + "line": 272 + }, + "16": { + "name": "parseNestedMapLines", + "decl": { "start": { "line": 284, "column": 9 }, "end": { "line": 284, "column": 29 } }, + "loc": { "start": { "line": 284, "column": 62 }, "end": { "line": 309, "column": null } }, + "line": 284 + }, + "17": { + "name": "serializeLockfile", + "decl": { "start": { "line": 315, "column": 16 }, "end": { "line": 315, "column": 34 } }, + "loc": { "start": { "line": 315, "column": 62 }, "end": { "line": 328, "column": null } }, + "line": 315 + }, + "18": { + "name": "serializeBlock", + "decl": { "start": { "line": 330, "column": 16 }, "end": { "line": 330, "column": 31 } }, + "loc": { "start": { "line": 330, "column": 61 }, "end": { "line": 364, "column": null } }, + "line": 330 + }, + "19": { + "name": "getScalar", + "decl": { "start": { "line": 370, "column": 16 }, "end": { "line": 370, "column": 26 } }, + "loc": { "start": { "line": 370, "column": 87 }, "end": { "line": 374, "column": null } }, + "line": 370 + }, + "20": { + "name": "getMap", + "decl": { "start": { "line": 376, "column": 16 }, "end": { "line": 376, "column": null } }, + "loc": { "start": { "line": 379, "column": 41 }, "end": { "line": 383, "column": null } }, + "line": 379 + }, + "21": { + "name": "getNestedMap", + "decl": { "start": { "line": 385, "column": 16 }, "end": { "line": 385, "column": null } }, + "loc": { "start": { "line": 388, "column": 61 }, "end": { "line": 392, "column": null } }, + "line": 388 + } + }, + "branchMap": { + "0": { + "loc": { "start": { "line": 51, "column": 2 }, "end": { "line": 51, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 51, "column": 2 }, "end": { "line": 51, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 51 + }, + "1": { + "loc": { "start": { "line": 53, "column": 2 }, "end": { "line": 53, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 53, "column": 2 }, "end": { "line": 53, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 53 + }, + "2": { + "loc": { "start": { "line": 56, "column": 2 }, "end": { "line": 56, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 56, "column": 2 }, "end": { "line": 56, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 56 + }, + "3": { + "loc": { "start": { "line": 56, "column": 6 }, "end": { "line": 56, "column": 54 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 56, "column": 6 }, "end": { "line": 56, "column": 26 } }, + { "start": { "line": 56, "column": 26 }, "end": { "line": 56, "column": 54 } } + ], + "line": 56 + }, + "4": { + "loc": { "start": { "line": 67, "column": 2 }, "end": { "line": 67, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 67, "column": 2 }, "end": { "line": 67, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 67 + }, + "5": { + "loc": { "start": { "line": 69, "column": 2 }, "end": { "line": 69, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 69, "column": 2 }, "end": { "line": 69, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 69 + }, + "6": { + "loc": { "start": { "line": 71, "column": 2 }, "end": { "line": 71, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 71, "column": 2 }, "end": { "line": 71, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 71 + }, + "7": { + "loc": { "start": { "line": 85, "column": 4 }, "end": { "line": 88, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 85, "column": 4 }, "end": { "line": 88, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 85 + }, + "8": { + "loc": { "start": { "line": 85, "column": 8 }, "end": { "line": 85, "column": 58 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 85, "column": 8 }, "end": { "line": 85, "column": 40 } }, + { "start": { "line": 85, "column": 40 }, "end": { "line": 85, "column": 58 } } + ], + "line": 85 + }, + "9": { + "loc": { "start": { "line": 87, "column": 6 }, "end": { "line": 87, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 87, "column": 6 }, "end": { "line": 87, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 87 + }, + "10": { + "loc": { "start": { "line": 103, "column": 4 }, "end": { "line": 106, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 103, "column": 4 }, "end": { "line": 106, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 103 + }, + "11": { + "loc": { "start": { "line": 105, "column": 6 }, "end": { "line": 105, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 105, "column": 6 }, "end": { "line": 105, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 105 + }, + "12": { + "loc": { "start": { "line": 122, "column": 4 }, "end": { "line": 125, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 122, "column": 4 }, "end": { "line": 125, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 122 + }, + "13": { + "loc": { "start": { "line": 122, "column": 8 }, "end": { "line": 122, "column": 58 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 122, "column": 8 }, "end": { "line": 122, "column": 40 } }, + { "start": { "line": 122, "column": 40 }, "end": { "line": 122, "column": 58 } } + ], + "line": 122 + }, + "14": { + "loc": { "start": { "line": 124, "column": 6 }, "end": { "line": 124, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 124, "column": 6 }, "end": { "line": 124, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 124 + }, + "15": { + "loc": { "start": { "line": 138, "column": 2 }, "end": { "line": 138, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 138, "column": 2 }, "end": { "line": 138, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 138 + }, + "16": { + "loc": { "start": { "line": 138, "column": 6 }, "end": { "line": 138, "column": 58 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 138, "column": 6 }, "end": { "line": 138, "column": 34 } }, + { "start": { "line": 138, "column": 34 }, "end": { "line": 138, "column": 58 } } + ], + "line": 138 + }, + "17": { + "loc": { "start": { "line": 140, "column": 2 }, "end": { "line": 140, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 140, "column": 2 }, "end": { "line": 140, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 140 + }, + "18": { + "loc": { "start": { "line": 174, "column": 4 }, "end": { "line": 185, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 174, "column": 4 }, "end": { "line": 185, "column": null } }, + { "start": { "line": 176, "column": 11 }, "end": { "line": 185, "column": null } } + ], + "line": 174 + }, + "19": { + "loc": { "start": { "line": 174, "column": 8 }, "end": { "line": 174, "column": 45 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 174, "column": 8 }, "end": { "line": 174, "column": 32 } }, + { "start": { "line": 174, "column": 32 }, "end": { "line": 174, "column": 45 } } + ], + "line": 174 + }, + "20": { + "loc": { "start": { "line": 176, "column": 11 }, "end": { "line": 185, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 176, "column": 11 }, "end": { "line": 185, "column": null } }, + { "start": { "line": 183, "column": 11 }, "end": { "line": 185, "column": null } } + ], + "line": 176 + }, + "21": { + "loc": { "start": { "line": 179, "column": 8 }, "end": { "line": 179, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 179, "column": 8 }, "end": { "line": 179, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 179 + }, + "22": { + "loc": { "start": { "line": 198, "column": 4 }, "end": { "line": 205, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 198, "column": 4 }, "end": { "line": 205, "column": null } }, + { "start": { "line": 200, "column": 11 }, "end": { "line": 205, "column": null } } + ], + "line": 198 + }, + "23": { + "loc": { "start": { "line": 198, "column": 8 }, "end": { "line": 198, "column": 78 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 198, "column": 8 }, "end": { "line": 198, "column": 33 } }, + { "start": { "line": 198, "column": 33 }, "end": { "line": 198, "column": 58 } }, + { "start": { "line": 198, "column": 58 }, "end": { "line": 198, "column": 78 } } + ], + "line": 198 + }, + "24": { + "loc": { "start": { "line": 202, "column": 6 }, "end": { "line": 204, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 202, "column": 6 }, "end": { "line": 204, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 202 + }, + "25": { + "loc": { "start": { "line": 218, "column": 2 }, "end": { "line": 220, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 218, "column": 2 }, "end": { "line": 220, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 218 + }, + "26": { + "loc": { "start": { "line": 218, "column": 6 }, "end": { "line": 218, "column": 56 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 218, "column": 6 }, "end": { "line": 218, "column": 33 } }, + { "start": { "line": 218, "column": 33 }, "end": { "line": 218, "column": 56 } } + ], + "line": 218 + }, + "27": { + "loc": { "start": { "line": 233, "column": 4 }, "end": { "line": 236, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 233, "column": 4 }, "end": { "line": 236, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 233 + }, + "28": { + "loc": { "start": { "line": 239, "column": 4 }, "end": { "line": 248, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 239, "column": 4 }, "end": { "line": 248, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 239 + }, + "29": { + "loc": { "start": { "line": 239, "column": 8 }, "end": { "line": 239, "column": 44 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 239, "column": 8 }, "end": { "line": 239, "column": 23 } }, + { "start": { "line": 239, "column": 23 }, "end": { "line": 239, "column": 44 } } + ], + "line": 239 + }, + "30": { + "loc": { "start": { "line": 241, "column": 15 }, "end": { "line": 241, "column": null } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 241, "column": 15 }, "end": { "line": 241, "column": 41 } }, + { "start": { "line": 241, "column": 41 }, "end": { "line": 241, "column": null } } + ], + "line": 241 + }, + "31": { + "loc": { "start": { "line": 243, "column": 6 }, "end": { "line": 247, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 243, "column": 6 }, "end": { "line": 247, "column": null } }, + { "start": { "line": 245, "column": 13 }, "end": { "line": 247, "column": null } } + ], + "line": 243 + }, + "32": { + "loc": { "start": { "line": 262, "column": 4 }, "end": { "line": 267, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 262, "column": 4 }, "end": { "line": 267, "column": null } }, + { "start": { "line": 264, "column": 11 }, "end": { "line": 267, "column": null } } + ], + "line": 262 + }, + "33": { + "loc": { "start": { "line": 262, "column": 8 }, "end": { "line": 262, "column": 59 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 262, "column": 8 }, "end": { "line": 262, "column": 33 } }, + { "start": { "line": 262, "column": 33 }, "end": { "line": 262, "column": 59 } } + ], + "line": 262 + }, + "34": { + "loc": { "start": { "line": 266, "column": 6 }, "end": { "line": 266, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 266, "column": 6 }, "end": { "line": 266, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 266 + }, + "35": { + "loc": { "start": { "line": 275, "column": 4 }, "end": { "line": 275, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 275, "column": 4 }, "end": { "line": 275, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 275 + }, + "36": { + "loc": { "start": { "line": 275, "column": 8 }, "end": { "line": 275, "column": 63 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 275, "column": 8 }, "end": { "line": 275, "column": 36 } }, + { "start": { "line": 275, "column": 36 }, "end": { "line": 275, "column": 63 } } + ], + "line": 275 + }, + "37": { + "loc": { "start": { "line": 277, "column": 4 }, "end": { "line": 279, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 277, "column": 4 }, "end": { "line": 279, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 277 + }, + "38": { + "loc": { "start": { "line": 289, "column": 4 }, "end": { "line": 289, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 289, "column": 4 }, "end": { "line": 289, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 289 + }, + "39": { + "loc": { "start": { "line": 291, "column": 4 }, "end": { "line": 299, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 291, "column": 4 }, "end": { "line": 299, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 291 + }, + "40": { + "loc": { "start": { "line": 292, "column": 6 }, "end": { "line": 297, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 292, "column": 6 }, "end": { "line": 297, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 292 + }, + "41": { + "loc": { "start": { "line": 294, "column": 8 }, "end": { "line": 296, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 294, "column": 8 }, "end": { "line": 296, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 294 + }, + "42": { + "loc": { "start": { "line": 302, "column": 4 }, "end": { "line": 305, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 302, "column": 4 }, "end": { "line": 305, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 302 + }, + "43": { + "loc": { "start": { "line": 318, "column": 2 }, "end": { "line": 320, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 318, "column": 2 }, "end": { "line": 320, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 318 + }, + "44": { + "loc": { "start": { "line": 335, "column": 4 }, "end": { "line": 360, "column": null } }, + "type": "switch", + "locations": [ + { "start": { "line": 336, "column": 6 }, "end": { "line": 338, "column": null } }, + { "start": { "line": 339, "column": 6 }, "end": { "line": 344, "column": null } }, + { "start": { "line": 345, "column": 6 }, "end": { "line": 353, "column": null } } + ], + "line": 335 + }, + "45": { + "loc": { "start": { "line": 372, "column": 2 }, "end": { "line": 372, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 372, "column": 2 }, "end": { "line": 372, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 372 + }, + "46": { + "loc": { "start": { "line": 372, "column": 6 }, "end": { "line": 372, "column": 41 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 372, "column": 6 }, "end": { "line": 372, "column": 16 } }, + { "start": { "line": 372, "column": 16 }, "end": { "line": 372, "column": 41 } } + ], + "line": 372 + }, + "47": { + "loc": { "start": { "line": 381, "column": 2 }, "end": { "line": 381, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 381, "column": 2 }, "end": { "line": 381, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 381 + }, + "48": { + "loc": { "start": { "line": 381, "column": 6 }, "end": { "line": 381, "column": 38 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 381, "column": 6 }, "end": { "line": 381, "column": 16 } }, + { "start": { "line": 381, "column": 16 }, "end": { "line": 381, "column": 38 } } + ], + "line": 381 + }, + "49": { + "loc": { "start": { "line": 390, "column": 2 }, "end": { "line": 390, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 390, "column": 2 }, "end": { "line": 390, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 390 + }, + "50": { + "loc": { "start": { "line": 390, "column": 6 }, "end": { "line": 390, "column": 45 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 390, "column": 6 }, "end": { "line": 390, "column": 16 } }, + { "start": { "line": 390, "column": 16 }, "end": { "line": 390, "column": 45 } } + ], + "line": 390 + } + }, + "s": { + "0": 201, + "1": 201, + "2": 1, + "3": 200, + "4": 200, + "5": 0, + "6": 200, + "7": 200, + "8": 200, + "9": 60, + "10": 140, + "11": 61, + "12": 61, + "13": 1, + "14": 60, + "15": 60, + "16": 0, + "17": 60, + "18": 60, + "19": 0, + "20": 60, + "21": 57, + "22": 57, + "23": 55, + "24": 55, + "25": 55, + "26": 55, + "27": 55, + "28": 55, + "29": 0, + "30": 2, + "31": 15, + "32": 15, + "33": 14, + "34": 14, + "35": 14, + "36": 14, + "37": 14, + "38": 0, + "39": 1, + "40": 17, + "41": 17, + "42": 15, + "43": 15, + "44": 15, + "45": 15, + "46": 15, + "47": 15, + "48": 0, + "49": 2, + "50": 68, + "51": 0, + "52": 68, + "53": 68, + "54": 2, + "55": 66, + "56": 38, + "57": 38, + "58": 38, + "59": 38, + "60": 438, + "61": 38, + "62": 38, + "63": 38, + "64": 38, + "65": 46, + "66": 8, + "67": 38, + "68": 26, + "69": 26, + "70": 61, + "71": 26, + "72": 35, + "73": 26, + "74": 12, + "75": 38, + "76": 38, + "77": 38, + "78": 351, + "79": 57, + "80": 294, + "81": 294, + "82": 292, + "83": 38, + "84": 57, + "85": 57, + "86": 57, + "87": 57, + "88": 57, + "89": 56, + "90": 1, + "91": 57, + "92": 57, + "93": 201, + "94": 201, + "95": 140, + "96": 140, + "97": 61, + "98": 61, + "99": 57, + "100": 70, + "101": 57, + "102": 13, + "103": 44, + "104": 57, + "105": 57, + "106": 57, + "107": 292, + "108": 201, + "109": 91, + "110": 91, + "111": 91, + "112": 57, + "113": 44, + "114": 44, + "115": 57, + "116": 0, + "117": 57, + "118": 57, + "119": 55, + "120": 44, + "121": 13, + "122": 13, + "123": 13, + "124": 34, + "125": 0, + "126": 34, + "127": 19, + "128": 17, + "129": 17, + "130": 15, + "131": 19, + "132": 15, + "133": 15, + "134": 14, + "135": 14, + "136": 13, + "137": 14, + "138": 14, + "139": 13, + "140": 14, + "141": 18, + "142": 18, + "143": 14, + "144": 20, + "145": 20, + "146": 20, + "147": 59, + "148": 46, + "149": 46, + "150": 11, + "151": 11, + "152": 17, + "153": 11, + "154": 2, + "155": 2, + "156": 2, + "157": 2, + "158": 2, + "159": 2, + "160": 20, + "161": 20, + "162": 20, + "163": 3, + "164": 17, + "165": 63, + "166": 63, + "167": 32, + "168": 31, + "169": 18, + "170": 18, + "171": 10, + "172": 8 + }, + "f": { + "0": 201, + "1": 61, + "2": 57, + "3": 15, + "4": 17, + "5": 68, + "6": 38, + "7": 438, + "8": 38, + "9": 38, + "10": 57, + "11": 57, + "12": 57, + "13": 70, + "14": 57, + "15": 44, + "16": 13, + "17": 14, + "18": 20, + "19": 20, + "20": 63, + "21": 18 + }, + "b": { + "0": [1, 200], + "1": [0, 200], + "2": [60, 140], + "3": [200, 140], + "4": [1, 60], + "5": [0, 60], + "6": [0, 60], + "7": [55, 0], + "8": [55, 55], + "9": [55, 0], + "10": [14, 0], + "11": [14, 0], + "12": [15, 0], + "13": [15, 15], + "14": [15, 0], + "15": [0, 68], + "16": [68, 68], + "17": [2, 66], + "18": [8, 38], + "19": [46, 43], + "20": [26, 12], + "21": [26, 35], + "22": [57, 294], + "23": [351, 59, 58], + "24": [292, 2], + "25": [56, 1], + "26": [57, 56], + "27": [140, 61], + "28": [57, 4], + "29": [61, 60], + "30": [70, 68], + "31": [13, 44], + "32": [201, 91], + "33": [292, 292], + "34": [91, 0], + "35": [0, 57], + "36": [57, 57], + "37": [55, 2], + "38": [0, 34], + "39": [19, 15], + "40": [17, 2], + "41": [15, 2], + "42": [14, 1], + "43": [13, 1], + "44": [46, 11, 2], + "45": [3, 17], + "46": [20, 18], + "47": [32, 31], + "48": [63, 32], + "49": [10, 8], + "50": [18, 9] + }, + "meta": { + "lastBranch": 51, + "lastFunction": 22, + "lastStatement": 173, + "seen": { + "f:49:9:49:21": 0, + "s:50:19:50:Infinity": 0, + "b:51:2:51:Infinity:undefined:undefined:undefined:undefined": 0, + "s:51:2:51:Infinity": 1, + "s:51:23:51:Infinity": 2, + "s:52:15:52:Infinity": 3, + "b:53:2:53:Infinity:undefined:undefined:undefined:undefined": 1, + "s:53:2:53:Infinity": 4, + "s:53:25:53:Infinity": 5, + "s:54:15:54:Infinity": 6, + "s:55:14:55:Infinity": 7, + "b:56:2:56:Infinity:undefined:undefined:undefined:undefined": 2, + "s:56:2:56:Infinity": 8, + "b:56:6:56:26:56:26:56:54": 3, + "s:56:54:56:Infinity": 9, + "s:57:2:57:Infinity": 10, + "f:65:9:65:28": 1, + "s:66:19:66:Infinity": 11, + "b:67:2:67:Infinity:undefined:undefined:undefined:undefined": 4, + "s:67:2:67:Infinity": 12, + "s:67:23:67:Infinity": 13, + "s:68:15:68:Infinity": 14, + "b:69:2:69:Infinity:undefined:undefined:undefined:undefined": 5, + "s:69:2:69:Infinity": 15, + "s:69:25:69:Infinity": 16, + "s:70:15:70:Infinity": 17, + "b:71:2:71:Infinity:undefined:undefined:undefined:undefined": 6, + "s:71:2:71:Infinity": 18, + "s:71:32:71:Infinity": 19, + "s:72:2:72:Infinity": 20, + "f:80:9:80:23": 2, + "s:81:17:81:Infinity": 21, + "s:82:2:90:Infinity": 22, + "s:83:17:83:Infinity": 23, + "s:84:18:84:Infinity": 24, + "b:85:4:88:Infinity:undefined:undefined:undefined:undefined": 7, + "s:85:4:88:Infinity": 25, + "b:85:8:85:40:85:40:85:58": 8, + "s:86:18:86:Infinity": 26, + "b:87:6:87:Infinity:undefined:undefined:undefined:undefined": 9, + "s:87:6:87:Infinity": 27, + "s:87:26:87:Infinity": 28, + "s:89:4:89:Infinity": 29, + "s:91:2:91:Infinity": 30, + "f:99:9:99:24": 3, + "s:100:17:100:Infinity": 31, + "s:101:2:108:Infinity": 32, + "s:102:17:102:Infinity": 33, + "b:103:4:106:Infinity:undefined:undefined:undefined:undefined": 10, + "s:103:4:106:Infinity": 34, + "s:104:18:104:Infinity": 35, + "b:105:6:105:Infinity:undefined:undefined:undefined:undefined": 11, + "s:105:6:105:Infinity": 36, + "s:105:26:105:Infinity": 37, + "s:107:4:107:Infinity": 38, + "s:109:2:109:Infinity": 39, + "f:117:9:117:25": 4, + "s:118:17:118:Infinity": 40, + "s:119:2:127:Infinity": 41, + "s:120:17:120:Infinity": 42, + "s:121:18:121:Infinity": 43, + "b:122:4:125:Infinity:undefined:undefined:undefined:undefined": 12, + "s:122:4:125:Infinity": 44, + "b:122:8:122:40:122:40:122:58": 13, + "s:123:19:123:Infinity": 45, + "b:124:6:124:Infinity:undefined:undefined:undefined:undefined": 14, + "s:124:6:124:Infinity": 46, + "s:124:27:124:Infinity": 47, + "s:126:4:126:Infinity": 48, + "s:128:2:128:Infinity": 49, + "f:137:9:137:27": 5, + "b:138:2:138:Infinity:undefined:undefined:undefined:undefined": 15, + "s:138:2:138:Infinity": 50, + "b:138:6:138:34:138:34:138:58": 16, + "s:138:58:138:Infinity": 51, + "s:139:19:139:Infinity": 52, + "b:140:2:140:Infinity:undefined:undefined:undefined:undefined": 17, + "s:140:2:140:Infinity": 53, + "s:140:23:140:Infinity": 54, + "s:141:2:141:Infinity": 55, + "f:155:16:155:30": 6, + "s:156:16:156:Infinity": 56, + "s:158:22:158:Infinity": 57, + "s:159:19:159:Infinity": 58, + "s:161:21:161:Infinity": 59, + "f:161:46:161:54": 7, + "s:161:60:161:68": 60, + "s:162:17:162:Infinity": 61, + "s:164:2:164:Infinity": 62, + "f:171:9:171:25": 8, + "s:172:10:172:Infinity": 63, + "s:173:2:186:Infinity": 64, + "b:174:4:185:Infinity:176:11:185:Infinity": 18, + "s:174:4:185:Infinity": 65, + "b:174:8:174:32:174:32:174:45": 19, + "s:175:6:175:Infinity": 66, + "b:176:11:185:Infinity:183:11:185:Infinity": 20, + "s:176:11:185:Infinity": 67, + "s:177:6:177:Infinity": 68, + "s:178:6:181:Infinity": 69, + "b:179:8:179:Infinity:undefined:undefined:undefined:undefined": 21, + "s:179:8:179:Infinity": 70, + "s:179:40:179:Infinity": 71, + "s:180:8:180:Infinity": 72, + "s:182:6:182:Infinity": 73, + "s:184:6:184:Infinity": 74, + "s:187:2:187:Infinity": 75, + "f:195:9:195:30": 9, + "s:196:31:196:Infinity": 76, + "s:197:2:206:Infinity": 77, + "b:198:4:205:Infinity:200:11:205:Infinity": 22, + "s:198:4:205:Infinity": 78, + "b:198:8:198:33:198:33:198:58:198:58:198:78": 23, + "s:199:6:199:Infinity": 79, + "s:201:22:201:Infinity": 80, + "b:202:6:204:Infinity:undefined:undefined:undefined:undefined": 24, + "s:202:6:204:Infinity": 81, + "s:203:8:203:Infinity": 82, + "s:207:2:207:Infinity": 83, + "f:210:9:210:25": 10, + "s:211:22:211:Infinity": 84, + "s:212:17:212:Infinity": 85, + "s:213:2:213:Infinity": 86, + "f:216:9:216:26": 11, + "s:217:18:217:Infinity": 87, + "b:218:2:220:Infinity:undefined:undefined:undefined:undefined": 25, + "s:218:2:220:Infinity": 88, + "b:218:6:218:33:218:33:218:56": 26, + "s:219:4:219:Infinity": 89, + "s:221:2:221:Infinity": 90, + "f:228:9:228:21": 12, + "s:229:52:229:Infinity": 91, + "s:231:2:249:Infinity": 92, + "s:232:19:232:Infinity": 93, + "b:233:4:236:Infinity:undefined:undefined:undefined:undefined": 27, + "s:233:4:236:Infinity": 94, + "s:234:6:234:Infinity": 95, + "s:235:6:235:Infinity": 96, + "s:238:24:238:Infinity": 97, + "b:239:4:248:Infinity:undefined:undefined:undefined:undefined": 28, + "s:239:4:248:Infinity": 98, + "b:239:8:239:23:239:23:239:44": 29, + "s:240:23:242:Infinity": 99, + "f:240:32:240:Infinity": 13, + "s:241:15:241:Infinity": 100, + "b:241:15:241:41:241:41:241:Infinity": 30, + "b:243:6:247:Infinity:245:13:247:Infinity": 31, + "s:243:6:247:Infinity": 101, + "s:244:8:244:Infinity": 102, + "s:246:8:246:Infinity": 103, + "s:251:2:251:Infinity": 104, + "f:259:9:259:22": 14, + "s:260:31:260:Infinity": 105, + "s:261:2:268:Infinity": 106, + "b:262:4:267:Infinity:264:11:267:Infinity": 32, + "s:262:4:267:Infinity": 107, + "b:262:8:262:33:262:33:262:59": 33, + "s:263:6:263:Infinity": 108, + "s:265:22:265:Infinity": 109, + "b:266:6:266:Infinity:undefined:undefined:undefined:undefined": 34, + "s:266:6:266:Infinity": 110, + "s:266:19:266:Infinity": 111, + "s:269:2:269:Infinity": 112, + "f:272:9:272:23": 15, + "s:273:45:273:Infinity": 113, + "s:274:2:280:Infinity": 114, + "b:275:4:275:Infinity:undefined:undefined:undefined:undefined": 35, + "s:275:4:275:Infinity": 115, + "b:275:8:275:36:275:36:275:63": 36, + "s:275:63:275:Infinity": 116, + "s:276:15:276:Infinity": 117, + "b:277:4:279:Infinity:undefined:undefined:undefined:undefined": 37, + "s:277:4:279:Infinity": 118, + "s:278:6:278:Infinity": 119, + "s:281:2:281:Infinity": 120, + "f:284:9:284:29": 16, + "s:285:65:285:Infinity": 121, + "s:286:56:286:Infinity": 122, + "s:288:2:306:Infinity": 123, + "b:289:4:289:Infinity:undefined:undefined:undefined:undefined": 38, + "s:289:4:289:Infinity": 124, + "s:289:34:289:Infinity": 125, + "b:291:4:299:Infinity:undefined:undefined:undefined:undefined": 39, + "s:291:4:299:Infinity": 126, + "b:292:6:297:Infinity:undefined:undefined:undefined:undefined": 40, + "s:292:6:297:Infinity": 127, + "s:293:19:293:Infinity": 128, + "b:294:8:296:Infinity:undefined:undefined:undefined:undefined": 41, + "s:294:8:296:Infinity": 129, + "s:295:10:295:Infinity": 130, + "s:298:6:298:Infinity": 131, + "s:301:16:301:Infinity": 132, + "b:302:4:305:Infinity:undefined:undefined:undefined:undefined": 42, + "s:302:4:305:Infinity": 133, + "s:303:6:303:Infinity": 134, + "s:304:6:304:Infinity": 135, + "s:308:2:308:Infinity": 136, + "f:315:16:315:34": 17, + "s:316:26:316:Infinity": 137, + "b:318:2:320:Infinity:undefined:undefined:undefined:undefined": 43, + "s:318:2:320:Infinity": 138, + "s:319:4:319:Infinity": 139, + "s:322:2:325:Infinity": 140, + "s:323:4:323:Infinity": 141, + "s:324:4:324:Infinity": 142, + "s:327:2:327:Infinity": 143, + "f:330:16:330:31": 18, + "s:331:25:331:Infinity": 144, + "s:332:16:332:Infinity": 145, + "s:334:2:361:Infinity": 146, + "b:336:6:338:Infinity:339:6:344:Infinity:345:6:353:Infinity": 44, + "s:335:4:360:Infinity": 147, + "s:337:8:337:Infinity": 148, + "s:338:8:338:Infinity": 149, + "s:340:8:340:Infinity": 150, + "s:341:8:343:Infinity": 151, + "s:342:10:342:Infinity": 152, + "s:344:8:344:Infinity": 153, + "s:346:8:346:Infinity": 154, + "s:347:8:352:Infinity": 155, + "s:348:10:348:Infinity": 156, + "s:349:10:351:Infinity": 157, + "s:350:12:350:Infinity": 158, + "s:353:8:353:Infinity": 159, + "s:363:2:363:Infinity": 160, + "f:370:16:370:26": 19, + "s:371:16:371:Infinity": 161, + "b:372:2:372:Infinity:undefined:undefined:undefined:undefined": 45, + "s:372:2:372:Infinity": 162, + "b:372:6:372:16:372:16:372:41": 46, + "s:372:41:372:Infinity": 163, + "s:373:2:373:Infinity": 164, + "f:376:16:376:Infinity": 20, + "s:380:16:380:Infinity": 165, + "b:381:2:381:Infinity:undefined:undefined:undefined:undefined": 47, + "s:381:2:381:Infinity": 166, + "b:381:6:381:16:381:16:381:38": 48, + "s:381:38:381:Infinity": 167, + "s:382:2:382:Infinity": 168, + "f:385:16:385:Infinity": 21, + "s:389:16:389:Infinity": 169, + "b:390:2:390:Infinity:undefined:undefined:undefined:undefined": 49, + "s:390:2:390:Infinity": 170, + "b:390:6:390:16:390:16:390:45": 50, + "s:390:45:390:Infinity": 171, + "s:391:2:391:Infinity": 172 + }, + "fnNames": {} + } + }, + "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/modules/generate-manifests/index.ts": { + "path": "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/modules/generate-manifests/index.ts", + "statementMap": { + "0": { "start": { "line": 18, "column": 30 }, "end": { "line": 18, "column": null } }, + "1": { "start": { "line": 20, "column": 21 }, "end": { "line": 20, "column": null } }, + "2": { "start": { "line": 32, "column": 2 }, "end": { "line": 32, "column": null } }, + "3": { "start": { "line": 33, "column": 28 }, "end": { "line": 33, "column": null } }, + "4": { "start": { "line": 35, "column": 2 }, "end": { "line": 35, "column": null } }, + "5": { "start": { "line": 36, "column": 2 }, "end": { "line": 38, "column": null } }, + "6": { "start": { "line": 37, "column": 4 }, "end": { "line": 37, "column": null } }, + "7": { "start": { "line": 40, "column": 23 }, "end": { "line": 40, "column": null } }, + "8": { "start": { "line": 41, "column": 2 }, "end": { "line": 41, "column": null } }, + "9": { "start": { "line": 42, "column": 2 }, "end": { "line": 42, "column": null } }, + "10": { "start": { "line": 44, "column": 2 }, "end": { "line": 47, "column": null } }, + "11": { "start": { "line": 45, "column": 4 }, "end": { "line": 45, "column": null } }, + "12": { "start": { "line": 46, "column": 4 }, "end": { "line": 46, "column": null } }, + "13": { "start": { "line": 49, "column": 28 }, "end": { "line": 49, "column": null } }, + "14": { "start": { "line": 50, "column": 24 }, "end": { "line": 50, "column": null } }, + "15": { "start": { "line": 51, "column": 2 }, "end": { "line": 51, "column": null } }, + "16": { "start": { "line": 52, "column": 2 }, "end": { "line": 52, "column": null } }, + "17": { "start": { "line": 56, "column": 2 }, "end": { "line": 64, "column": null } }, + "18": { "start": { "line": 57, "column": 20 }, "end": { "line": 62, "column": null } }, + "19": { "start": { "line": 63, "column": 4 }, "end": { "line": 63, "column": null } }, + "20": { "start": { "line": 63, "column": 34 }, "end": { "line": 63, "column": 94 } }, + "21": { "start": { "line": 63, "column": 74 }, "end": { "line": 63, "column": 93 } }, + "22": { "start": { "line": 72, "column": 27 }, "end": { "line": 72, "column": null } }, + "23": { "start": { "line": 73, "column": 44 }, "end": { "line": 73, "column": null } }, + "24": { "start": { "line": 75, "column": 2 }, "end": { "line": 78, "column": null } }, + "25": { "start": { "line": 76, "column": 18 }, "end": { "line": 76, "column": null } }, + "26": { "start": { "line": 77, "column": 4 }, "end": { "line": 77, "column": null } }, + "27": { "start": { "line": 77, "column": 15 }, "end": { "line": 77, "column": null } }, + "28": { "start": { "line": 80, "column": 2 }, "end": { "line": 80, "column": null } }, + "29": { "start": { "line": 80, "column": 26 }, "end": { "line": 80, "column": 54 } }, + "30": { "start": { "line": 81, "column": 2 }, "end": { "line": 81, "column": null } }, + "31": { "start": { "line": 90, "column": 22 }, "end": { "line": 90, "column": null } }, + "32": { "start": { "line": 91, "column": 2 }, "end": { "line": 91, "column": null } }, + "33": { "start": { "line": 91, "column": 35 }, "end": { "line": 91, "column": null } }, + "34": { "start": { "line": 93, "column": 18 }, "end": { "line": 93, "column": null } }, + "35": { "start": { "line": 94, "column": 29 }, "end": { "line": 94, "column": null } }, + "36": { "start": { "line": 95, "column": 18 }, "end": { "line": 95, "column": null } }, + "37": { "start": { "line": 97, "column": 2 }, "end": { "line": 104, "column": null } }, + "38": { "start": { "line": 98, "column": 20 }, "end": { "line": 98, "column": null } }, + "39": { "start": { "line": 99, "column": 4 }, "end": { "line": 103, "column": null } }, + "40": { "start": { "line": 100, "column": 6 }, "end": { "line": 100, "column": null } }, + "41": { "start": { "line": 100, "column": 46 }, "end": { "line": 100, "column": 67 } }, + "42": { "start": { "line": 100, "column": 70 }, "end": { "line": 100, "column": null } }, + "43": { "start": { "line": 101, "column": 22 }, "end": { "line": 101, "column": null } }, + "44": { "start": { "line": 102, "column": 6 }, "end": { "line": 102, "column": null } }, + "45": { "start": { "line": 102, "column": 34 }, "end": { "line": 102, "column": null } }, + "46": { "start": { "line": 106, "column": 2 }, "end": { "line": 106, "column": null } }, + "47": { "start": { "line": 109, "column": 19 }, "end": { "line": 115, "column": null } }, + "48": { "start": { "line": 121, "column": 18 }, "end": { "line": 121, "column": null } }, + "49": { "start": { "line": 122, "column": 2 }, "end": { "line": 122, "column": null } }, + "50": { "start": { "line": 122, "column": 41 }, "end": { "line": 122, "column": null } }, + "51": { "start": { "line": 124, "column": 39 }, "end": { "line": 128, "column": null } }, + "52": { "start": { "line": 130, "column": 2 }, "end": { "line": 134, "column": null } }, + "53": { "start": { "line": 131, "column": 4 }, "end": { "line": 133, "column": null } }, + "54": { "start": { "line": 132, "column": 6 }, "end": { "line": 132, "column": null } }, + "55": { "start": { "line": 136, "column": 2 }, "end": { "line": 138, "column": null } }, + "56": { "start": { "line": 137, "column": 4 }, "end": { "line": 137, "column": null } }, + "57": { "start": { "line": 140, "column": 2 }, "end": { "line": 140, "column": null } }, + "58": { "start": { "line": 151, "column": 2 }, "end": { "line": 156, "column": null } }, + "59": { "start": { "line": 152, "column": 18 }, "end": { "line": 152, "column": null } }, + "60": { "start": { "line": 155, "column": 4 }, "end": { "line": 155, "column": null } }, + "61": { "start": { "line": 157, "column": 2 }, "end": { "line": 157, "column": null } }, + "62": { "start": { "line": 157, "column": 35 }, "end": { "line": 157, "column": null } }, + "63": { "start": { "line": 158, "column": 2 }, "end": { "line": 158, "column": null } }, + "64": { "start": { "line": 166, "column": 27 }, "end": { "line": 166, "column": null } }, + "65": { "start": { "line": 167, "column": 2 }, "end": { "line": 167, "column": null } }, + "66": { "start": { "line": 169, "column": 23 }, "end": { "line": 169, "column": null } }, + "67": { "start": { "line": 170, "column": 2 }, "end": { "line": 172, "column": null } }, + "68": { "start": { "line": 171, "column": 4 }, "end": { "line": 171, "column": null } }, + "69": { "start": { "line": 174, "column": 22 }, "end": { "line": 174, "column": null } }, + "70": { "start": { "line": 175, "column": 18 }, "end": { "line": 175, "column": null } }, + "71": { "start": { "line": 176, "column": 2 }, "end": { "line": 176, "column": null } }, + "72": { "start": { "line": 178, "column": 2 }, "end": { "line": 178, "column": null } }, + "73": { "start": { "line": 180, "column": 2 }, "end": { "line": 183, "column": null } }, + "74": { "start": { "line": 182, "column": 41 }, "end": { "line": 182, "column": 69 } }, + "75": { "start": { "line": 191, "column": 28 }, "end": { "line": 191, "column": null } }, + "76": { "start": { "line": 192, "column": 2 }, "end": { "line": 197, "column": null } }, + "77": { "start": { "line": 193, "column": 4 }, "end": { "line": 196, "column": null } }, + "78": { "start": { "line": 198, "column": 18 }, "end": { "line": 198, "column": null } }, + "79": { "start": { "line": 199, "column": 2 }, "end": { "line": 201, "column": null } }, + "80": { "start": { "line": 200, "column": 4 }, "end": { "line": 200, "column": null } }, + "81": { "start": { "line": 202, "column": 2 }, "end": { "line": 202, "column": null } }, + "82": { "start": { "line": 218, "column": 19 }, "end": { "line": 218, "column": null } }, + "83": { "start": { "line": 219, "column": 43 }, "end": { "line": 219, "column": null } }, + "84": { "start": { "line": 221, "column": 2 }, "end": { "line": 254, "column": null } }, + "85": { "start": { "line": 222, "column": 4 }, "end": { "line": 222, "column": null } }, + "86": { "start": { "line": 222, "column": 39 }, "end": { "line": 222, "column": 64 } }, + "87": { "start": { "line": 222, "column": 67 }, "end": { "line": 222, "column": null } }, + "88": { "start": { "line": 224, "column": 23 }, "end": { "line": 224, "column": null } }, + "89": { "start": { "line": 227, "column": 22 }, "end": { "line": 227, "column": null } }, + "90": { "start": { "line": 228, "column": 17 }, "end": { "line": 228, "column": null } }, + "91": { "start": { "line": 229, "column": 4 }, "end": { "line": 229, "column": null } }, + "92": { "start": { "line": 229, "column": 15 }, "end": { "line": 229, "column": null } }, + "93": { "start": { "line": 231, "column": 20 }, "end": { "line": 231, "column": null } }, + "94": { "start": { "line": 232, "column": 4 }, "end": { "line": 232, "column": null } }, + "95": { "start": { "line": 232, "column": 18 }, "end": { "line": 232, "column": null } }, + "96": { "start": { "line": 234, "column": 41 }, "end": { "line": 234, "column": null } }, + "97": { "start": { "line": 236, "column": 17 }, "end": { "line": 236, "column": null } }, + "98": { "start": { "line": 237, "column": 4 }, "end": { "line": 237, "column": null } }, + "99": { "start": { "line": 237, "column": 14 }, "end": { "line": 237, "column": null } }, + "100": { "start": { "line": 239, "column": 18 }, "end": { "line": 239, "column": null } }, + "101": { "start": { "line": 240, "column": 4 }, "end": { "line": 240, "column": null } }, + "102": { "start": { "line": 240, "column": 15 }, "end": { "line": 240, "column": null } }, + "103": { "start": { "line": 242, "column": 22 }, "end": { "line": 242, "column": null } }, + "104": { "start": { "line": 243, "column": 4 }, "end": { "line": 245, "column": null } }, + "105": { "start": { "line": 244, "column": 6 }, "end": { "line": 244, "column": null } }, + "106": { "start": { "line": 247, "column": 21 }, "end": { "line": 247, "column": null } }, + "107": { "start": { "line": 248, "column": 4 }, "end": { "line": 248, "column": null } }, + "108": { "start": { "line": 248, "column": 18 }, "end": { "line": 248, "column": null } }, + "109": { "start": { "line": 250, "column": 16 }, "end": { "line": 250, "column": null } }, + "110": { "start": { "line": 251, "column": 4 }, "end": { "line": 251, "column": null } }, + "111": { "start": { "line": 251, "column": 13 }, "end": { "line": 251, "column": null } }, + "112": { "start": { "line": 253, "column": 4 }, "end": { "line": 253, "column": null } }, + "113": { "start": { "line": 256, "column": 2 }, "end": { "line": 256, "column": null } }, + "114": { "start": { "line": 260, "column": 41 }, "end": { "line": 260, "column": null } }, + "115": { "start": { "line": 261, "column": 2 }, "end": { "line": 263, "column": null } }, + "116": { "start": { "line": 262, "column": 4 }, "end": { "line": 262, "column": null } }, + "117": { "start": { "line": 264, "column": 2 }, "end": { "line": 264, "column": null } }, + "118": { "start": { "line": 271, "column": 14 }, "end": { "line": 271, "column": null } }, + "119": { "start": { "line": 272, "column": 2 }, "end": { "line": 272, "column": null } }, + "120": { "start": { "line": 272, "column": 12 }, "end": { "line": 272, "column": null } }, + "121": { "start": { "line": 273, "column": 19 }, "end": { "line": 273, "column": null } }, + "122": { "start": { "line": 281, "column": 18 }, "end": { "line": 281, "column": null } }, + "123": { "start": { "line": 284, "column": 61 }, "end": { "line": 284, "column": null } }, + "124": { "start": { "line": 285, "column": 2 }, "end": { "line": 292, "column": null } }, + "125": { "start": { "line": 286, "column": 44 }, "end": { "line": 286, "column": null } }, + "126": { "start": { "line": 287, "column": 4 }, "end": { "line": 287, "column": null } }, + "127": { "start": { "line": 288, "column": 4 }, "end": { "line": 291, "column": null } }, + "128": { "start": { "line": 289, "column": 23 }, "end": { "line": 289, "column": null } }, + "129": { "start": { "line": 290, "column": 6 }, "end": { "line": 290, "column": null } }, + "130": { "start": { "line": 293, "column": 2 }, "end": { "line": 293, "column": null } }, + "131": { "start": { "line": 305, "column": 14 }, "end": { "line": 305, "column": null } }, + "132": { "start": { "line": 306, "column": 2 }, "end": { "line": 306, "column": null } }, + "133": { "start": { "line": 308, "column": 19 }, "end": { "line": 308, "column": null } }, + "134": { "start": { "line": 309, "column": 2 }, "end": { "line": 313, "column": null } }, + "135": { "start": { "line": 310, "column": 4 }, "end": { "line": 312, "column": null } }, + "136": { "start": { "line": 315, "column": 28 }, "end": { "line": 315, "column": null } }, + "137": { "start": { "line": 316, "column": 2 }, "end": { "line": 323, "column": null } }, + "138": { "start": { "line": 322, "column": 4 }, "end": { "line": 322, "column": null } }, + "139": { "start": { "line": 324, "column": 21 }, "end": { "line": 324, "column": null } }, + "140": { "start": { "line": 325, "column": 2 }, "end": { "line": 336, "column": null } }, + "141": { "start": { "line": 326, "column": 4 }, "end": { "line": 335, "column": null } }, + "142": { "start": { "line": 334, "column": 6 }, "end": { "line": 334, "column": null } }, + "143": { "start": { "line": 338, "column": 31 }, "end": { "line": 338, "column": null } }, + "144": { "start": { "line": 339, "column": 2 }, "end": { "line": 344, "column": null } }, + "145": { "start": { "line": 340, "column": 21 }, "end": { "line": 340, "column": null } }, + "146": { "start": { "line": 341, "column": 4 }, "end": { "line": 343, "column": null } }, + "147": { "start": { "line": 342, "column": 6 }, "end": { "line": 342, "column": null } }, + "148": { "start": { "line": 346, "column": 2 }, "end": { "line": 351, "column": null } }, + "149": { "start": { "line": 347, "column": 4 }, "end": { "line": 350, "column": null } }, + "150": { "start": { "line": 353, "column": 2 }, "end": { "line": 353, "column": null } }, + "151": { "start": { "line": 361, "column": 2 }, "end": { "line": 361, "column": null } } + }, + "fnMap": { + "0": { + "name": "run", + "decl": { "start": { "line": 31, "column": 22 }, "end": { "line": 31, "column": 26 } }, + "loc": { "start": { "line": 31, "column": 61 }, "end": { "line": 53, "column": null } }, + "line": 31 + }, + "1": { + "name": "manifestHasBackstageDeps", + "decl": { "start": { "line": 55, "column": 9 }, "end": { "line": 55, "column": 34 } }, + "loc": { "start": { "line": 55, "column": 72 }, "end": { "line": 65, "column": null } }, + "line": 55 + }, + "2": { + "name": "(anonymous_2)", + "decl": { "start": { "line": 56, "column": 27 }, "end": { "line": 56, "column": 33 } }, + "loc": { "start": { "line": 56, "column": 41 }, "end": { "line": 64, "column": 3 } }, + "line": 56 + }, + "3": { + "name": "(anonymous_3)", + "decl": { "start": { "line": 63, "column": 19 }, "end": { "line": 63, "column": 25 } }, + "loc": { "start": { "line": 63, "column": 34 }, "end": { "line": 63, "column": 94 } }, + "line": 63 + }, + "4": { + "name": "(anonymous_4)", + "decl": { "start": { "line": 63, "column": 62 }, "end": { "line": 63, "column": 68 } }, + "loc": { "start": { "line": 63, "column": 74 }, "end": { "line": 63, "column": 93 } }, + "line": 63 + }, + "5": { + "name": "generateWorkspaceManifest", + "decl": { "start": { "line": 71, "column": 9 }, "end": { "line": 71, "column": 35 } }, + "loc": { "start": { "line": 71, "column": 74 }, "end": { "line": 82, "column": null } }, + "line": 71 + }, + "6": { + "name": "(anonymous_6)", + "decl": { "start": { "line": 80, "column": 11 }, "end": { "line": 80, "column": 17 } }, + "loc": { "start": { "line": 80, "column": 26 }, "end": { "line": 80, "column": 54 } }, + "line": 80 + }, + "7": { + "name": "findWorkspacePackageJsonFiles", + "decl": { "start": { "line": 89, "column": 16 }, "end": { "line": 89, "column": 46 } }, + "loc": { "start": { "line": 89, "column": 79 }, "end": { "line": 107, "column": null } }, + "line": 89 + }, + "8": { + "name": "(anonymous_8)", + "decl": { "start": { "line": 100, "column": 32 }, "end": { "line": 100, "column": 38 } }, + "loc": { "start": { "line": 100, "column": 46 }, "end": { "line": 100, "column": 67 } }, + "line": 100 + }, + "9": { + "name": "extractPackageInfo", + "decl": { "start": { "line": 117, "column": 16 }, "end": { "line": 117, "column": null } }, + "loc": { "start": { "line": 120, "column": 32 }, "end": { "line": 141, "column": null } }, + "line": 120 + }, + "10": { + "name": "normalizeBin", + "decl": { "start": { "line": 147, "column": 16 }, "end": { "line": 147, "column": null } }, + "loc": { "start": { "line": 150, "column": 38 }, "end": { "line": 159, "column": null } }, + "line": 150 + }, + "11": { + "name": "generateBackstageManifest", + "decl": { "start": { "line": 165, "column": 15 }, "end": { "line": 165, "column": 41 } }, + "loc": { "start": { "line": 165, "column": 89 }, "end": { "line": 184, "column": null } }, + "line": 165 + }, + "12": { + "name": "(anonymous_12)", + "decl": { "start": { "line": 182, "column": 22 }, "end": { "line": 182, "column": 32 } }, + "loc": { "start": { "line": 182, "column": 41 }, "end": { "line": 182, "column": 69 } }, + "line": 182 + }, + "13": { + "name": "getBackstageVersion", + "decl": { "start": { "line": 190, "column": 16 }, "end": { "line": 190, "column": 36 } }, + "loc": { "start": { "line": 190, "column": 67 }, "end": { "line": 203, "column": null } }, + "line": 190 + }, + "14": { + "name": "extractBackstageEntries", + "decl": { "start": { "line": 217, "column": 16 }, "end": { "line": 217, "column": 40 } }, + "loc": { "start": { "line": 217, "column": 86 }, "end": { "line": 257, "column": null } }, + "line": 217 + }, + "15": { + "name": "(anonymous_15)", + "decl": { "start": { "line": 222, "column": 27 }, "end": { "line": 222, "column": 33 } }, + "loc": { "start": { "line": 222, "column": 39 }, "end": { "line": 222, "column": 64 } }, + "line": 222 + }, + "16": { + "name": "stripMapQuotes", + "decl": { "start": { "line": 259, "column": 9 }, "end": { "line": 259, "column": 24 } }, + "loc": { "start": { "line": 259, "column": 80 }, "end": { "line": 265, "column": null } }, + "line": 259 + }, + "17": { + "name": "getStrippedMap", + "decl": { "start": { "line": 267, "column": 9 }, "end": { "line": 267, "column": null } }, + "loc": { "start": { "line": 270, "column": 38 }, "end": { "line": 276, "column": null } }, + "line": 270 + }, + "18": { + "name": "convertNestedMapValues", + "decl": { "start": { "line": 278, "column": 9 }, "end": { "line": 278, "column": 32 } }, + "loc": { "start": { "line": 280, "column": 56 }, "end": { "line": 294, "column": null } }, + "line": 280 + }, + "19": { + "name": "validateBackstageVersions", + "decl": { "start": { "line": 300, "column": 15 }, "end": { "line": 300, "column": null } }, + "loc": { "start": { "line": 304, "column": 17 }, "end": { "line": 354, "column": null } }, + "line": 304 + }, + "20": { + "name": "writeJson", + "decl": { "start": { "line": 360, "column": 9 }, "end": { "line": 360, "column": 19 } }, + "loc": { "start": { "line": 360, "column": 58 }, "end": { "line": 362, "column": null } }, + "line": 360 + } + }, + "branchMap": { + "0": { + "loc": { "start": { "line": 44, "column": 2 }, "end": { "line": 47, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 44, "column": 2 }, "end": { "line": 47, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 44 + }, + "1": { + "loc": { "start": { "line": 63, "column": 34 }, "end": { "line": 63, "column": 94 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 63, "column": 34 }, "end": { "line": 63, "column": 42 } }, + { "start": { "line": 63, "column": 42 }, "end": { "line": 63, "column": 94 } } + ], + "line": 63 + }, + "2": { + "loc": { "start": { "line": 77, "column": 4 }, "end": { "line": 77, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 77, "column": 4 }, "end": { "line": 77, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 77 + }, + "3": { + "loc": { "start": { "line": 91, "column": 2 }, "end": { "line": 91, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 91, "column": 2 }, "end": { "line": 91, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 91 + }, + "4": { + "loc": { "start": { "line": 94, "column": 29 }, "end": { "line": 94, "column": null } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 94, "column": 29 }, "end": { "line": 94, "column": 51 } }, + { "start": { "line": 94, "column": 51 }, "end": { "line": 94, "column": null } } + ], + "line": 94 + }, + "5": { + "loc": { "start": { "line": 100, "column": 6 }, "end": { "line": 100, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 100, "column": 6 }, "end": { "line": 100, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 100 + }, + "6": { + "loc": { "start": { "line": 102, "column": 6 }, "end": { "line": 102, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 102, "column": 6 }, "end": { "line": 102, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 102 + }, + "7": { + "loc": { "start": { "line": 122, "column": 2 }, "end": { "line": 122, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 122, "column": 2 }, "end": { "line": 122, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 122 + }, + "8": { + "loc": { "start": { "line": 122, "column": 6 }, "end": { "line": 122, "column": 41 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 122, "column": 6 }, "end": { "line": 122, "column": 23 } }, + { "start": { "line": 122, "column": 23 }, "end": { "line": 122, "column": 41 } } + ], + "line": 122 + }, + "9": { + "loc": { "start": { "line": 131, "column": 4 }, "end": { "line": 133, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 131, "column": 4 }, "end": { "line": 133, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 131 + }, + "10": { + "loc": { "start": { "line": 131, "column": 8 }, "end": { "line": 131, "column": 66 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 131, "column": 8 }, "end": { "line": 131, "column": 26 } }, + { "start": { "line": 131, "column": 26 }, "end": { "line": 131, "column": 66 } } + ], + "line": 131 + }, + "11": { + "loc": { "start": { "line": 136, "column": 2 }, "end": { "line": 138, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 136, "column": 2 }, "end": { "line": 138, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 136 + }, + "12": { + "loc": { "start": { "line": 151, "column": 2 }, "end": { "line": 156, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 151, "column": 2 }, "end": { "line": 156, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 151 + }, + "13": { + "loc": { "start": { "line": 157, "column": 2 }, "end": { "line": 157, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 157, "column": 2 }, "end": { "line": 157, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 157 + }, + "14": { + "loc": { "start": { "line": 170, "column": 2 }, "end": { "line": 172, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 170, "column": 2 }, "end": { "line": 172, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 170 + }, + "15": { + "loc": { "start": { "line": 192, "column": 2 }, "end": { "line": 197, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 192, "column": 2 }, "end": { "line": 197, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 192 + }, + "16": { + "loc": { "start": { "line": 199, "column": 2 }, "end": { "line": 201, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 199, "column": 2 }, "end": { "line": 201, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 199 + }, + "17": { + "loc": { "start": { "line": 222, "column": 4 }, "end": { "line": 222, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 222, "column": 4 }, "end": { "line": 222, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 222 + }, + "18": { + "loc": { "start": { "line": 229, "column": 4 }, "end": { "line": 229, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 229, "column": 4 }, "end": { "line": 229, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 229 + }, + "19": { + "loc": { "start": { "line": 232, "column": 4 }, "end": { "line": 232, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 232, "column": 4 }, "end": { "line": 232, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 232 + }, + "20": { + "loc": { "start": { "line": 237, "column": 4 }, "end": { "line": 237, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 237, "column": 4 }, "end": { "line": 237, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 237 + }, + "21": { + "loc": { "start": { "line": 240, "column": 4 }, "end": { "line": 240, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 240, "column": 4 }, "end": { "line": 240, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 240 + }, + "22": { + "loc": { "start": { "line": 243, "column": 4 }, "end": { "line": 245, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 243, "column": 4 }, "end": { "line": 245, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 243 + }, + "23": { + "loc": { "start": { "line": 248, "column": 4 }, "end": { "line": 248, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 248, "column": 4 }, "end": { "line": 248, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 248 + }, + "24": { + "loc": { "start": { "line": 251, "column": 4 }, "end": { "line": 251, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 251, "column": 4 }, "end": { "line": 251, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 251 + }, + "25": { + "loc": { "start": { "line": 272, "column": 2 }, "end": { "line": 272, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 272, "column": 2 }, "end": { "line": 272, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 272 + }, + "26": { + "loc": { "start": { "line": 290, "column": 20 }, "end": { "line": 290, "column": null } }, + "type": "cond-expr", + "locations": [ + { "start": { "line": 290, "column": 42 }, "end": { "line": 290, "column": 49 } }, + { "start": { "line": 290, "column": 49 }, "end": { "line": 290, "column": null } } + ], + "line": 290 + }, + "27": { + "loc": { "start": { "line": 290, "column": 49 }, "end": { "line": 290, "column": null } }, + "type": "cond-expr", + "locations": [ + { "start": { "line": 290, "column": 72 }, "end": { "line": 290, "column": 80 } }, + { "start": { "line": 290, "column": 80 }, "end": { "line": 290, "column": null } } + ], + "line": 290 + }, + "28": { + "loc": { "start": { "line": 309, "column": 2 }, "end": { "line": 313, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 309, "column": 2 }, "end": { "line": 313, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 309 + }, + "29": { + "loc": { "start": { "line": 316, "column": 2 }, "end": { "line": 323, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 316, "column": 2 }, "end": { "line": 323, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 316 + }, + "30": { + "loc": { "start": { "line": 317, "column": 4 }, "end": { "line": 320, "column": null } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 317, "column": 4 }, "end": { "line": 317, "column": null } }, + { "start": { "line": 318, "column": 4 }, "end": { "line": 318, "column": null } }, + { "start": { "line": 319, "column": 4 }, "end": { "line": 319, "column": null } }, + { "start": { "line": 320, "column": 4 }, "end": { "line": 320, "column": null } } + ], + "line": 317 + }, + "31": { + "loc": { "start": { "line": 326, "column": 4 }, "end": { "line": 335, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 326, "column": 4 }, "end": { "line": 335, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 326 + }, + "32": { + "loc": { "start": { "line": 327, "column": 6 }, "end": { "line": 332, "column": null } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 327, "column": 6 }, "end": { "line": 327, "column": null } }, + { "start": { "line": 328, "column": 6 }, "end": { "line": 328, "column": null } }, + { "start": { "line": 329, "column": 6 }, "end": { "line": 329, "column": null } }, + { "start": { "line": 330, "column": 6 }, "end": { "line": 330, "column": null } }, + { "start": { "line": 331, "column": 6 }, "end": { "line": 331, "column": null } }, + { "start": { "line": 332, "column": 6 }, "end": { "line": 332, "column": null } } + ], + "line": 327 + }, + "33": { + "loc": { "start": { "line": 341, "column": 4 }, "end": { "line": 343, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 341, "column": 4 }, "end": { "line": 343, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 341 + }, + "34": { + "loc": { "start": { "line": 341, "column": 8 }, "end": { "line": 341, "column": 48 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 341, "column": 8 }, "end": { "line": 341, "column": 20 } }, + { "start": { "line": 341, "column": 20 }, "end": { "line": 341, "column": 48 } } + ], + "line": 341 + }, + "35": { + "loc": { "start": { "line": 346, "column": 2 }, "end": { "line": 351, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 346, "column": 2 }, "end": { "line": 351, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 346 + } + }, + "s": { + "0": 3, + "1": 3, + "2": 12, + "3": 12, + "4": 12, + "5": 12, + "6": 24, + "7": 12, + "8": 12, + "9": 12, + "10": 12, + "11": 3, + "12": 3, + "13": 9, + "14": 3, + "15": 3, + "16": 3, + "17": 12, + "18": 15, + "19": 15, + "20": 33, + "21": 18, + "22": 12, + "23": 12, + "24": 12, + "25": 25, + "26": 25, + "27": 24, + "28": 12, + "29": 14, + "30": 12, + "31": 18, + "32": 18, + "33": 1, + "34": 17, + "35": 17, + "36": 18, + "37": 18, + "38": 15, + "39": 15, + "40": 26, + "41": 52, + "42": 2, + "43": 24, + "44": 24, + "45": 21, + "46": 17, + "47": 3, + "48": 27, + "49": 27, + "50": 3, + "51": 24, + "52": 24, + "53": 120, + "54": 17, + "55": 24, + "56": 4, + "57": 24, + "58": 8, + "59": 5, + "60": 5, + "61": 3, + "62": 2, + "63": 1, + "64": 9, + "65": 9, + "66": 9, + "67": 9, + "68": 1, + "69": 6, + "70": 6, + "71": 6, + "72": 6, + "73": 3, + "74": 3, + "75": 11, + "76": 11, + "77": 2, + "78": 9, + "79": 9, + "80": 1, + "81": 8, + "82": 10, + "83": 10, + "84": 10, + "85": 24, + "86": 24, + "87": 7, + "88": 17, + "89": 17, + "90": 17, + "91": 24, + "92": 1, + "93": 16, + "94": 16, + "95": 1, + "96": 15, + "97": 15, + "98": 15, + "99": 7, + "100": 15, + "101": 15, + "102": 11, + "103": 15, + "104": 15, + "105": 7, + "106": 15, + "107": 15, + "108": 6, + "109": 15, + "110": 15, + "111": 6, + "112": 15, + "113": 10, + "114": 30, + "115": 30, + "116": 35, + "117": 30, + "118": 60, + "119": 60, + "120": 30, + "121": 30, + "122": 7, + "123": 7, + "124": 7, + "125": 8, + "126": 8, + "127": 8, + "128": 9, + "129": 9, + "130": 7, + "131": 6, + "132": 6, + "133": 6, + "134": 6, + "135": 1, + "136": 5, + "137": 5, + "138": 1, + "139": 4, + "140": 4, + "141": 17, + "142": 13, + "143": 4, + "144": 4, + "145": 7, + "146": 7, + "147": 1, + "148": 4, + "149": 1, + "150": 3, + "151": 15 + }, + "f": { + "0": 12, + "1": 12, + "2": 15, + "3": 33, + "4": 18, + "5": 12, + "6": 14, + "7": 18, + "8": 52, + "9": 27, + "10": 8, + "11": 9, + "12": 3, + "13": 11, + "14": 10, + "15": 24, + "16": 30, + "17": 60, + "18": 7, + "19": 6, + "20": 15 + }, + "b": { + "0": [3, 9], + "1": [33, 16], + "2": [24, 1], + "3": [1, 17], + "4": [17, 2], + "5": [2, 24], + "6": [21, 3], + "7": [3, 24], + "8": [27, 25], + "9": [17, 103], + "10": [120, 17], + "11": [4, 20], + "12": [5, 3], + "13": [2, 1], + "14": [1, 8], + "15": [2, 9], + "16": [1, 8], + "17": [7, 17], + "18": [1, 23], + "19": [1, 15], + "20": [7, 8], + "21": [11, 4], + "22": [7, 8], + "23": [6, 9], + "24": [6, 9], + "25": [30, 30], + "26": [7, 2], + "27": [1, 1], + "28": [1, 5], + "29": [1, 4], + "30": [5, 5, 5, 4], + "31": [13, 4], + "32": [17, 16, 15, 14, 14, 13], + "33": [1, 6], + "34": [7, 7], + "35": [1, 3] + }, + "meta": { + "lastBranch": 36, + "lastFunction": 21, + "lastStatement": 152, + "seen": { + "s:18:30:18:Infinity": 0, + "s:20:21:20:Infinity": 1, + "f:31:22:31:26": 0, + "s:32:2:32:Infinity": 2, + "s:33:28:33:Infinity": 3, + "s:35:2:35:Infinity": 4, + "s:36:2:38:Infinity": 5, + "s:37:4:37:Infinity": 6, + "s:40:23:40:Infinity": 7, + "s:41:2:41:Infinity": 8, + "s:42:2:42:Infinity": 9, + "b:44:2:47:Infinity:undefined:undefined:undefined:undefined": 0, + "s:44:2:47:Infinity": 10, + "s:45:4:45:Infinity": 11, + "s:46:4:46:Infinity": 12, + "s:49:28:49:Infinity": 13, + "s:50:24:50:Infinity": 14, + "s:51:2:51:Infinity": 15, + "s:52:2:52:Infinity": 16, + "f:55:9:55:34": 1, + "s:56:2:64:Infinity": 17, + "f:56:27:56:33": 2, + "s:57:20:62:Infinity": 18, + "s:63:4:63:Infinity": 19, + "f:63:19:63:25": 3, + "s:63:34:63:94": 20, + "b:63:34:63:42:63:42:63:94": 1, + "f:63:62:63:68": 4, + "s:63:74:63:93": 21, + "f:71:9:71:35": 5, + "s:72:27:72:Infinity": 22, + "s:73:44:73:Infinity": 23, + "s:75:2:78:Infinity": 24, + "s:76:18:76:Infinity": 25, + "b:77:4:77:Infinity:undefined:undefined:undefined:undefined": 2, + "s:77:4:77:Infinity": 26, + "s:77:15:77:Infinity": 27, + "s:80:2:80:Infinity": 28, + "f:80:11:80:17": 6, + "s:80:26:80:54": 29, + "s:81:2:81:Infinity": 30, + "f:89:16:89:46": 7, + "s:90:22:90:Infinity": 31, + "b:91:2:91:Infinity:undefined:undefined:undefined:undefined": 3, + "s:91:2:91:Infinity": 32, + "s:91:35:91:Infinity": 33, + "s:93:18:93:Infinity": 34, + "s:94:29:94:Infinity": 35, + "b:94:29:94:51:94:51:94:Infinity": 4, + "s:95:18:95:Infinity": 36, + "s:97:2:104:Infinity": 37, + "s:98:20:98:Infinity": 38, + "s:99:4:103:Infinity": 39, + "b:100:6:100:Infinity:undefined:undefined:undefined:undefined": 5, + "s:100:6:100:Infinity": 40, + "f:100:32:100:38": 8, + "s:100:46:100:67": 41, + "s:100:70:100:Infinity": 42, + "s:101:22:101:Infinity": 43, + "b:102:6:102:Infinity:undefined:undefined:undefined:undefined": 6, + "s:102:6:102:Infinity": 44, + "s:102:34:102:Infinity": 45, + "s:106:2:106:Infinity": 46, + "s:109:19:115:Infinity": 47, + "f:117:16:117:Infinity": 9, + "s:121:18:121:Infinity": 48, + "b:122:2:122:Infinity:undefined:undefined:undefined:undefined": 7, + "s:122:2:122:Infinity": 49, + "b:122:6:122:23:122:23:122:41": 8, + "s:122:41:122:Infinity": 50, + "s:124:39:128:Infinity": 51, + "s:130:2:134:Infinity": 52, + "b:131:4:133:Infinity:undefined:undefined:undefined:undefined": 9, + "s:131:4:133:Infinity": 53, + "b:131:8:131:26:131:26:131:66": 10, + "s:132:6:132:Infinity": 54, + "b:136:2:138:Infinity:undefined:undefined:undefined:undefined": 11, + "s:136:2:138:Infinity": 55, + "s:137:4:137:Infinity": 56, + "s:140:2:140:Infinity": 57, + "f:147:16:147:Infinity": 10, + "b:151:2:156:Infinity:undefined:undefined:undefined:undefined": 12, + "s:151:2:156:Infinity": 58, + "s:152:18:152:Infinity": 59, + "s:155:4:155:Infinity": 60, + "b:157:2:157:Infinity:undefined:undefined:undefined:undefined": 13, + "s:157:2:157:Infinity": 61, + "s:157:35:157:Infinity": 62, + "s:158:2:158:Infinity": 63, + "f:165:15:165:41": 11, + "s:166:27:166:Infinity": 64, + "s:167:2:167:Infinity": 65, + "s:169:23:169:Infinity": 66, + "b:170:2:172:Infinity:undefined:undefined:undefined:undefined": 14, + "s:170:2:172:Infinity": 67, + "s:171:4:171:Infinity": 68, + "s:174:22:174:Infinity": 69, + "s:175:18:175:Infinity": 70, + "s:176:2:176:Infinity": 71, + "s:178:2:178:Infinity": 72, + "s:180:2:183:Infinity": 73, + "f:182:22:182:32": 12, + "s:182:41:182:69": 74, + "f:190:16:190:36": 13, + "s:191:28:191:Infinity": 75, + "b:192:2:197:Infinity:undefined:undefined:undefined:undefined": 15, + "s:192:2:197:Infinity": 76, + "s:193:4:196:Infinity": 77, + "s:198:18:198:Infinity": 78, + "b:199:2:201:Infinity:undefined:undefined:undefined:undefined": 16, + "s:199:2:201:Infinity": 79, + "s:200:4:200:Infinity": 80, + "s:202:2:202:Infinity": 81, + "f:217:16:217:40": 14, + "s:218:19:218:Infinity": 82, + "s:219:43:219:Infinity": 83, + "s:221:2:254:Infinity": 84, + "b:222:4:222:Infinity:undefined:undefined:undefined:undefined": 17, + "s:222:4:222:Infinity": 85, + "f:222:27:222:33": 15, + "s:222:39:222:64": 86, + "s:222:67:222:Infinity": 87, + "s:224:23:224:Infinity": 88, + "s:227:22:227:Infinity": 89, + "s:228:17:228:Infinity": 90, + "b:229:4:229:Infinity:undefined:undefined:undefined:undefined": 18, + "s:229:4:229:Infinity": 91, + "s:229:15:229:Infinity": 92, + "s:231:20:231:Infinity": 93, + "b:232:4:232:Infinity:undefined:undefined:undefined:undefined": 19, + "s:232:4:232:Infinity": 94, + "s:232:18:232:Infinity": 95, + "s:234:41:234:Infinity": 96, + "s:236:17:236:Infinity": 97, + "b:237:4:237:Infinity:undefined:undefined:undefined:undefined": 20, + "s:237:4:237:Infinity": 98, + "s:237:14:237:Infinity": 99, + "s:239:18:239:Infinity": 100, + "b:240:4:240:Infinity:undefined:undefined:undefined:undefined": 21, + "s:240:4:240:Infinity": 101, + "s:240:15:240:Infinity": 102, + "s:242:22:242:Infinity": 103, + "b:243:4:245:Infinity:undefined:undefined:undefined:undefined": 22, + "s:243:4:245:Infinity": 104, + "s:244:6:244:Infinity": 105, + "s:247:21:247:Infinity": 106, + "b:248:4:248:Infinity:undefined:undefined:undefined:undefined": 23, + "s:248:4:248:Infinity": 107, + "s:248:18:248:Infinity": 108, + "s:250:16:250:Infinity": 109, + "b:251:4:251:Infinity:undefined:undefined:undefined:undefined": 24, + "s:251:4:251:Infinity": 110, + "s:251:13:251:Infinity": 111, + "s:253:4:253:Infinity": 112, + "s:256:2:256:Infinity": 113, + "f:259:9:259:24": 16, + "s:260:41:260:Infinity": 114, + "s:261:2:263:Infinity": 115, + "s:262:4:262:Infinity": 116, + "s:264:2:264:Infinity": 117, + "f:267:9:267:Infinity": 17, + "s:271:14:271:Infinity": 118, + "b:272:2:272:Infinity:undefined:undefined:undefined:undefined": 25, + "s:272:2:272:Infinity": 119, + "s:272:12:272:Infinity": 120, + "s:273:19:273:Infinity": 121, + "f:278:9:278:32": 18, + "s:281:18:281:Infinity": 122, + "s:284:61:284:Infinity": 123, + "s:285:2:292:Infinity": 124, + "s:286:44:286:Infinity": 125, + "s:287:4:287:Infinity": 126, + "s:288:4:291:Infinity": 127, + "s:289:23:289:Infinity": 128, + "s:290:6:290:Infinity": 129, + "b:290:42:290:49:290:49:290:Infinity": 26, + "b:290:72:290:80:290:80:290:Infinity": 27, + "s:293:2:293:Infinity": 130, + "f:300:15:300:Infinity": 19, + "s:305:14:305:Infinity": 131, + "s:306:2:306:Infinity": 132, + "s:308:19:308:Infinity": 133, + "b:309:2:313:Infinity:undefined:undefined:undefined:undefined": 28, + "s:309:2:313:Infinity": 134, + "s:310:4:312:Infinity": 135, + "s:315:28:315:Infinity": 136, + "b:316:2:323:Infinity:undefined:undefined:undefined:undefined": 29, + "s:316:2:323:Infinity": 137, + "b:317:4:317:Infinity:318:4:318:Infinity:319:4:319:Infinity:320:4:320:Infinity": 30, + "s:322:4:322:Infinity": 138, + "s:324:21:324:Infinity": 139, + "s:325:2:336:Infinity": 140, + "b:326:4:335:Infinity:undefined:undefined:undefined:undefined": 31, + "s:326:4:335:Infinity": 141, + "b:327:6:327:Infinity:328:6:328:Infinity:329:6:329:Infinity:330:6:330:Infinity:331:6:331:Infinity:332:6:332:Infinity": 32, + "s:334:6:334:Infinity": 142, + "s:338:31:338:Infinity": 143, + "s:339:2:344:Infinity": 144, + "s:340:21:340:Infinity": 145, + "b:341:4:343:Infinity:undefined:undefined:undefined:undefined": 33, + "s:341:4:343:Infinity": 146, + "b:341:8:341:20:341:20:341:48": 34, + "s:342:6:342:Infinity": 147, + "b:346:2:351:Infinity:undefined:undefined:undefined:undefined": 35, + "s:346:2:351:Infinity": 148, + "s:347:4:350:Infinity": 149, + "s:353:2:353:Infinity": 150, + "f:360:9:360:19": 20, + "s:361:2:361:Infinity": 151 + }, + "fnNames": {} + } + }, + "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/modules/hermetic-prep/index.ts": { + "path": "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/modules/hermetic-prep/index.ts", + "statementMap": { + "0": { "start": { "line": 6, "column": 29 }, "end": { "line": 6, "column": null } }, + "1": { "start": { "line": 9, "column": 2 }, "end": { "line": 9, "column": null } }, + "2": { "start": { "line": 13, "column": 2 }, "end": { "line": 13, "column": null } }, + "3": { "start": { "line": 17, "column": 23 }, "end": { "line": 17, "column": null } }, + "4": { "start": { "line": 18, "column": 2 }, "end": { "line": 20, "column": null } }, + "5": { "start": { "line": 19, "column": 4 }, "end": { "line": 19, "column": null } }, + "6": { "start": { "line": 21, "column": 2 }, "end": { "line": 21, "column": null } }, + "7": { "start": { "line": 28, "column": 14 }, "end": { "line": 28, "column": null } }, + "8": { "start": { "line": 29, "column": 2 }, "end": { "line": 31, "column": null } }, + "9": { "start": { "line": 30, "column": 4 }, "end": { "line": 30, "column": null } }, + "10": { "start": { "line": 32, "column": 2 }, "end": { "line": 34, "column": null } }, + "11": { "start": { "line": 33, "column": 4 }, "end": { "line": 33, "column": null } }, + "12": { "start": { "line": 35, "column": 2 }, "end": { "line": 37, "column": null } }, + "13": { "start": { "line": 36, "column": 4 }, "end": { "line": 36, "column": null } }, + "14": { "start": { "line": 38, "column": 21 }, "end": { "line": 38, "column": null } }, + "15": { "start": { "line": 39, "column": 2 }, "end": { "line": 40, "column": null } }, + "16": { "start": { "line": 45, "column": 26 }, "end": { "line": 45, "column": null } }, + "17": { "start": { "line": 46, "column": 2 }, "end": { "line": 56, "column": null } }, + "18": { "start": { "line": 47, "column": 4 }, "end": { "line": 49, "column": null } }, + "19": { "start": { "line": 48, "column": 6 }, "end": { "line": 48, "column": null } }, + "20": { "start": { "line": 50, "column": 17 }, "end": { "line": 50, "column": null } }, + "21": { "start": { "line": 51, "column": 4 }, "end": { "line": 55, "column": null } }, + "22": { "start": { "line": 52, "column": 6 }, "end": { "line": 52, "column": null } }, + "23": { "start": { "line": 53, "column": 11 }, "end": { "line": 55, "column": null } }, + "24": { "start": { "line": 54, "column": 6 }, "end": { "line": 54, "column": null } }, + "25": { "start": { "line": 57, "column": 2 }, "end": { "line": 57, "column": null } }, + "26": { "start": { "line": 66, "column": 22 }, "end": { "line": 66, "column": null } }, + "27": { "start": { "line": 67, "column": 2 }, "end": { "line": 74, "column": null } }, + "28": { "start": { "line": 68, "column": 16 }, "end": { "line": 68, "column": null } }, + "29": { "start": { "line": 69, "column": 4 }, "end": { "line": 73, "column": null } }, + "30": { "start": { "line": 70, "column": 6 }, "end": { "line": 70, "column": null } }, + "31": { "start": { "line": 71, "column": 6 }, "end": { "line": 71, "column": null } }, + "32": { "start": { "line": 72, "column": 6 }, "end": { "line": 72, "column": null } }, + "33": { "start": { "line": 76, "column": 2 }, "end": { "line": 85, "column": null } }, + "34": { "start": { "line": 77, "column": 16 }, "end": { "line": 77, "column": null } }, + "35": { "start": { "line": 78, "column": 20 }, "end": { "line": 78, "column": null } }, + "36": { "start": { "line": 79, "column": 4 }, "end": { "line": 81, "column": null } }, + "37": { "start": { "line": 80, "column": 6 }, "end": { "line": 80, "column": null } }, + "38": { "start": { "line": 82, "column": 4 }, "end": { "line": 82, "column": null } }, + "39": { "start": { "line": 83, "column": 4 }, "end": { "line": 83, "column": null } }, + "40": { "start": { "line": 84, "column": 4 }, "end": { "line": 84, "column": null } } + }, + "fnMap": { + "0": { + "name": "writeJson", + "decl": { "start": { "line": 8, "column": 9 }, "end": { "line": 8, "column": 19 } }, + "loc": { "start": { "line": 8, "column": 59 }, "end": { "line": 10, "column": null } }, + "line": 8 + }, + "1": { + "name": "isRecord", + "decl": { "start": { "line": 12, "column": 9 }, "end": { "line": 12, "column": 18 } }, + "loc": { "start": { "line": 12, "column": 68 }, "end": { "line": 14, "column": null } }, + "line": 12 + }, + "2": { + "name": "readJsonObject", + "decl": { "start": { "line": 16, "column": 9 }, "end": { "line": 16, "column": 24 } }, + "loc": { "start": { "line": 16, "column": 67 }, "end": { "line": 22, "column": null } }, + "line": 16 + }, + "3": { + "name": "hasMonorepoPostinstall", + "decl": { "start": { "line": 24, "column": 9 }, "end": { "line": 24, "column": null } }, + "loc": { "start": { "line": 27, "column": 11 }, "end": { "line": 42, "column": null } }, + "line": 27 + }, + "4": { + "name": "walkPackageJson", + "decl": { "start": { "line": 44, "column": 9 }, "end": { "line": 44, "column": 25 } }, + "loc": { "start": { "line": 44, "column": 48 }, "end": { "line": 58, "column": null } }, + "line": 44 + }, + "5": { + "name": "run", + "decl": { "start": { "line": 65, "column": 22 }, "end": { "line": 65, "column": 26 } }, + "loc": { "start": { "line": 65, "column": 61 }, "end": { "line": 86, "column": null } }, + "line": 65 + } + }, + "branchMap": { + "0": { + "loc": { "start": { "line": 13, "column": 9 }, "end": { "line": 13, "column": null } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 13, "column": 9 }, "end": { "line": 13, "column": 38 } }, + { "start": { "line": 13, "column": 38 }, "end": { "line": 13, "column": 56 } }, + { "start": { "line": 13, "column": 56 }, "end": { "line": 13, "column": null } } + ], + "line": 13 + }, + "1": { + "loc": { "start": { "line": 18, "column": 2 }, "end": { "line": 20, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 18, "column": 2 }, "end": { "line": 20, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 18 + }, + "2": { + "loc": { "start": { "line": 29, "column": 2 }, "end": { "line": 31, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 29, "column": 2 }, "end": { "line": 31, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 29 + }, + "3": { + "loc": { "start": { "line": 32, "column": 2 }, "end": { "line": 34, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 32, "column": 2 }, "end": { "line": 34, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 32 + }, + "4": { + "loc": { "start": { "line": 35, "column": 2 }, "end": { "line": 37, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 35, "column": 2 }, "end": { "line": 37, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 35 + }, + "5": { + "loc": { "start": { "line": 40, "column": 4 }, "end": { "line": 40, "column": null } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 40, "column": 4 }, "end": { "line": 40, "column": 33 } }, + { "start": { "line": 40, "column": 33 }, "end": { "line": 40, "column": null } } + ], + "line": 40 + }, + "6": { + "loc": { "start": { "line": 47, "column": 4 }, "end": { "line": 49, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 47, "column": 4 }, "end": { "line": 49, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 47 + }, + "7": { + "loc": { "start": { "line": 51, "column": 4 }, "end": { "line": 55, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 51, "column": 4 }, "end": { "line": 55, "column": null } }, + { "start": { "line": 53, "column": 11 }, "end": { "line": 55, "column": null } } + ], + "line": 51 + }, + "8": { + "loc": { "start": { "line": 53, "column": 11 }, "end": { "line": 55, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 53, "column": 11 }, "end": { "line": 55, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 53 + }, + "9": { + "loc": { "start": { "line": 67, "column": 2 }, "end": { "line": 74, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 67, "column": 2 }, "end": { "line": 74, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 67 + }, + "10": { + "loc": { "start": { "line": 69, "column": 4 }, "end": { "line": 73, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 69, "column": 4 }, "end": { "line": 73, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 69 + }, + "11": { + "loc": { "start": { "line": 78, "column": 20 }, "end": { "line": 78, "column": null } }, + "type": "cond-expr", + "locations": [ + { "start": { "line": 78, "column": 44 }, "end": { "line": 78, "column": 58 } }, + { "start": { "line": 78, "column": 58 }, "end": { "line": 78, "column": null } } + ], + "line": 78 + }, + "12": { + "loc": { "start": { "line": 79, "column": 4 }, "end": { "line": 81, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 79, "column": 4 }, "end": { "line": 81, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 79 + }, + "13": { + "loc": { "start": { "line": 79, "column": 8 }, "end": { "line": 79, "column": 63 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 79, "column": 8 }, "end": { "line": 79, "column": 20 } }, + { "start": { "line": 79, "column": 20 }, "end": { "line": 79, "column": 63 } } + ], + "line": 79 + } + }, + "s": { + "0": 3, + "1": 6, + "2": 32, + "3": 21, + "4": 21, + "5": 1, + "6": 20, + "7": 6, + "8": 6, + "9": 1, + "10": 5, + "11": 3, + "12": 2, + "13": 1, + "14": 1, + "15": 1, + "16": 15, + "17": 15, + "18": 18, + "19": 1, + "20": 17, + "21": 17, + "22": 5, + "23": 12, + "24": 11, + "25": 15, + "26": 11, + "27": 11, + "28": 10, + "29": 10, + "30": 2, + "31": 2, + "32": 2, + "33": 10, + "34": 11, + "35": 11, + "36": 11, + "37": 7, + "38": 4, + "39": 4, + "40": 4 + }, + "f": { "0": 6, "1": 32, "2": 21, "3": 6, "4": 15, "5": 11 }, + "b": { + "0": [32, 27, 27], + "1": [1, 20], + "2": [1, 5], + "3": [3, 2], + "4": [1, 1], + "5": [1, 1], + "6": [1, 17], + "7": [5, 12], + "8": [11, 1], + "9": [10, 1], + "10": [2, 8], + "11": [6, 5], + "12": [7, 4], + "13": [11, 6] + }, + "meta": { + "lastBranch": 14, + "lastFunction": 6, + "lastStatement": 41, + "seen": { + "s:6:29:6:Infinity": 0, + "f:8:9:8:19": 0, + "s:9:2:9:Infinity": 1, + "f:12:9:12:18": 1, + "s:13:2:13:Infinity": 2, + "b:13:9:13:38:13:38:13:56:13:56:13:Infinity": 0, + "f:16:9:16:24": 2, + "s:17:23:17:Infinity": 3, + "b:18:2:20:Infinity:undefined:undefined:undefined:undefined": 1, + "s:18:2:20:Infinity": 4, + "s:19:4:19:Infinity": 5, + "s:21:2:21:Infinity": 6, + "f:24:9:24:Infinity": 3, + "s:28:14:28:Infinity": 7, + "b:29:2:31:Infinity:undefined:undefined:undefined:undefined": 2, + "s:29:2:31:Infinity": 8, + "s:30:4:30:Infinity": 9, + "b:32:2:34:Infinity:undefined:undefined:undefined:undefined": 3, + "s:32:2:34:Infinity": 10, + "s:33:4:33:Infinity": 11, + "b:35:2:37:Infinity:undefined:undefined:undefined:undefined": 4, + "s:35:2:37:Infinity": 12, + "s:36:4:36:Infinity": 13, + "s:38:21:38:Infinity": 14, + "s:39:2:40:Infinity": 15, + "b:40:4:40:33:40:33:40:Infinity": 5, + "f:44:9:44:25": 4, + "s:45:26:45:Infinity": 16, + "s:46:2:56:Infinity": 17, + "b:47:4:49:Infinity:undefined:undefined:undefined:undefined": 6, + "s:47:4:49:Infinity": 18, + "s:48:6:48:Infinity": 19, + "s:50:17:50:Infinity": 20, + "b:51:4:55:Infinity:53:11:55:Infinity": 7, + "s:51:4:55:Infinity": 21, + "s:52:6:52:Infinity": 22, + "b:53:11:55:Infinity:undefined:undefined:undefined:undefined": 8, + "s:53:11:55:Infinity": 23, + "s:54:6:54:Infinity": 24, + "s:57:2:57:Infinity": 25, + "f:65:22:65:26": 5, + "s:66:22:66:Infinity": 26, + "b:67:2:74:Infinity:undefined:undefined:undefined:undefined": 9, + "s:67:2:74:Infinity": 27, + "s:68:16:68:Infinity": 28, + "b:69:4:73:Infinity:undefined:undefined:undefined:undefined": 10, + "s:69:4:73:Infinity": 29, + "s:70:6:70:Infinity": 30, + "s:71:6:71:Infinity": 31, + "s:72:6:72:Infinity": 32, + "s:76:2:85:Infinity": 33, + "s:77:16:77:Infinity": 34, + "s:78:20:78:Infinity": 35, + "b:78:44:78:58:78:58:78:Infinity": 11, + "b:79:4:81:Infinity:undefined:undefined:undefined:undefined": 12, + "s:79:4:81:Infinity": 36, + "b:79:8:79:20:79:20:79:63": 13, + "s:80:6:80:Infinity": 37, + "s:82:4:82:Infinity": 38, + "s:83:4:83:Infinity": 39, + "s:84:4:84:Infinity": 40 + }, + "fnNames": {} + } + }, + "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/modules/make-self-contained/index.ts": { + "path": "/Users/dfestal/git/rhdh-plugin-export-utils/prepare-sources/lib/modules/make-self-contained/index.ts", + "statementMap": { + "0": { "start": { "line": 18, "column": 2 }, "end": { "line": 21, "column": null } }, + "1": { "start": { "line": 19, "column": 4 }, "end": { "line": 19, "column": null } }, + "2": { "start": { "line": 20, "column": 4 }, "end": { "line": 20, "column": null } }, + "3": { "start": { "line": 23, "column": 19 }, "end": { "line": 23, "column": null } }, + "4": { "start": { "line": 24, "column": 2 }, "end": { "line": 24, "column": null } }, + "5": { "start": { "line": 26, "column": 2 }, "end": { "line": 26, "column": null } }, + "6": { "start": { "line": 27, "column": 2 }, "end": { "line": 27, "column": null } }, + "7": { "start": { "line": 28, "column": 2 }, "end": { "line": 28, "column": null } }, + "8": { "start": { "line": 36, "column": 22 }, "end": { "line": 36, "column": null } }, + "9": { "start": { "line": 37, "column": 2 }, "end": { "line": 40, "column": null } }, + "10": { "start": { "line": 38, "column": 4 }, "end": { "line": 38, "column": null } }, + "11": { "start": { "line": 39, "column": 4 }, "end": { "line": 39, "column": null } }, + "12": { "start": { "line": 42, "column": 20 }, "end": { "line": 42, "column": null } }, + "13": { "start": { "line": 43, "column": 2 }, "end": { "line": 43, "column": null } }, + "14": { "start": { "line": 44, "column": 2 }, "end": { "line": 44, "column": null } }, + "15": { "start": { "line": 52, "column": 19 }, "end": { "line": 52, "column": null } }, + "16": { "start": { "line": 53, "column": 17 }, "end": { "line": 53, "column": null } }, + "17": { "start": { "line": 54, "column": 21 }, "end": { "line": 54, "column": null } }, + "18": { "start": { "line": 55, "column": 19 }, "end": { "line": 55, "column": null } }, + "19": { "start": { "line": 57, "column": 2 }, "end": { "line": 60, "column": null } }, + "20": { "start": { "line": 58, "column": 4 }, "end": { "line": 58, "column": null } }, + "21": { "start": { "line": 59, "column": 4 }, "end": { "line": 59, "column": null } }, + "22": { "start": { "line": 62, "column": 2 }, "end": { "line": 66, "column": null } }, + "23": { "start": { "line": 63, "column": 4 }, "end": { "line": 63, "column": null } }, + "24": { "start": { "line": 64, "column": 4 }, "end": { "line": 64, "column": null } }, + "25": { "start": { "line": 65, "column": 4 }, "end": { "line": 65, "column": null } }, + "26": { "start": { "line": 68, "column": 2 }, "end": { "line": 68, "column": null } }, + "27": { "start": { "line": 69, "column": 22 }, "end": { "line": 69, "column": null } }, + "28": { "start": { "line": 70, "column": 20 }, "end": { "line": 70, "column": null } }, + "29": { "start": { "line": 71, "column": 17 }, "end": { "line": 71, "column": null } }, + "30": { "start": { "line": 72, "column": 2 }, "end": { "line": 72, "column": null } }, + "31": { "start": { "line": 88, "column": 24 }, "end": { "line": 88, "column": null } }, + "32": { "start": { "line": 89, "column": 26 }, "end": { "line": 89, "column": null } }, + "33": { "start": { "line": 91, "column": 17 }, "end": { "line": 91, "column": null } }, + "34": { "start": { "line": 92, "column": 2 }, "end": { "line": 96, "column": null } }, + "35": { "start": { "line": 93, "column": 4 }, "end": { "line": 95, "column": null } }, + "36": { "start": { "line": 94, "column": 6 }, "end": { "line": 94, "column": null } }, + "37": { "start": { "line": 98, "column": 2 }, "end": { "line": 98, "column": null } }, + "38": { "start": { "line": 108, "column": 17 }, "end": { "line": 108, "column": null } }, + "39": { "start": { "line": 109, "column": 19 }, "end": { "line": 109, "column": null } }, + "40": { "start": { "line": 110, "column": 31 }, "end": { "line": 110, "column": null } }, + "41": { "start": { "line": 112, "column": 2 }, "end": { "line": 123, "column": null } }, + "42": { "start": { "line": 113, "column": 18 }, "end": { "line": 113, "column": null } }, + "43": { "start": { "line": 114, "column": 4 }, "end": { "line": 122, "column": null } }, + "44": { "start": { "line": 115, "column": 6 }, "end": { "line": 117, "column": null } }, + "45": { "start": { "line": 116, "column": 8 }, "end": { "line": 116, "column": null } }, + "46": { "start": { "line": 118, "column": 6 }, "end": { "line": 118, "column": null } }, + "47": { "start": { "line": 119, "column": 6 }, "end": { "line": 119, "column": null } }, + "48": { "start": { "line": 121, "column": 6 }, "end": { "line": 121, "column": null } }, + "49": { "start": { "line": 125, "column": 2 }, "end": { "line": 127, "column": null } }, + "50": { "start": { "line": 126, "column": 4 }, "end": { "line": 126, "column": null } }, + "51": { "start": { "line": 129, "column": 2 }, "end": { "line": 129, "column": null } }, + "52": { "start": { "line": 133, "column": 2 }, "end": { "line": 137, "column": null } }, + "53": { "start": { "line": 134, "column": 17 }, "end": { "line": 134, "column": null } }, + "54": { "start": { "line": 135, "column": 4 }, "end": { "line": 135, "column": null } }, + "55": { "start": { "line": 135, "column": 50 }, "end": { "line": 135, "column": null } }, + "56": { "start": { "line": 136, "column": 4 }, "end": { "line": 136, "column": null } }, + "57": { "start": { "line": 138, "column": 2 }, "end": { "line": 138, "column": null } }, + "58": { "start": { "line": 146, "column": 21 }, "end": { "line": 146, "column": null } }, + "59": { "start": { "line": 147, "column": 2 }, "end": { "line": 147, "column": null } }, + "60": { "start": { "line": 147, "column": 34 }, "end": { "line": 147, "column": null } }, + "61": { "start": { "line": 149, "column": 18 }, "end": { "line": 149, "column": null } }, + "62": { "start": { "line": 150, "column": 16 }, "end": { "line": 150, "column": null } }, + "63": { "start": { "line": 151, "column": 2 }, "end": { "line": 151, "column": null } }, + "64": { "start": { "line": 151, "column": 32 }, "end": { "line": 151, "column": null } }, + "65": { "start": { "line": 153, "column": 19 }, "end": { "line": 153, "column": null } }, + "66": { "start": { "line": 154, "column": 19 }, "end": { "line": 154, "column": null } }, + "67": { "start": { "line": 156, "column": 2 }, "end": { "line": 161, "column": null } }, + "68": { "start": { "line": 157, "column": 4 }, "end": { "line": 160, "column": null } }, + "69": { "start": { "line": 163, "column": 2 }, "end": { "line": 163, "column": null } } + }, + "fnMap": { + "0": { + "name": "run", + "decl": { "start": { "line": 17, "column": 22 }, "end": { "line": 17, "column": 26 } }, + "loc": { "start": { "line": 17, "column": 61 }, "end": { "line": 29, "column": null } }, + "line": 17 + }, + "1": { + "name": "mergeYarnDir", + "decl": { "start": { "line": 35, "column": 9 }, "end": { "line": 35, "column": 22 } }, + "loc": { "start": { "line": 35, "column": 66 }, "end": { "line": 45, "column": null } }, + "line": 35 + }, + "2": { + "name": "mergeYarnrcYml", + "decl": { "start": { "line": 51, "column": 9 }, "end": { "line": 51, "column": 24 } }, + "loc": { "start": { "line": 51, "column": 68 }, "end": { "line": 73, "column": null } }, + "line": 51 + }, + "3": { + "name": "mergeYamlByTopLevelKey", + "decl": { "start": { "line": 87, "column": 16 }, "end": { "line": 87, "column": 39 } }, + "loc": { "start": { "line": 87, "column": 83 }, "end": { "line": 99, "column": null } }, + "line": 87 + }, + "4": { + "name": "parseTopLevelBlocks", + "decl": { "start": { "line": 107, "column": 9 }, "end": { "line": 107, "column": 29 } }, + "loc": { "start": { "line": 107, "column": 67 }, "end": { "line": 130, "column": null } }, + "line": 107 + }, + "5": { + "name": "trimTrailingBlanks", + "decl": { "start": { "line": 132, "column": 9 }, "end": { "line": 132, "column": 28 } }, + "loc": { "start": { "line": 132, "column": 55 }, "end": { "line": 139, "column": null } }, + "line": 132 + }, + "6": { + "name": "validateYarnPath", + "decl": { "start": { "line": 145, "column": 9 }, "end": { "line": 145, "column": 26 } }, + "loc": { "start": { "line": 145, "column": 52 }, "end": { "line": 164, "column": null } }, + "line": 145 + } + }, + "branchMap": { + "0": { + "loc": { "start": { "line": 18, "column": 2 }, "end": { "line": 21, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 18, "column": 2 }, "end": { "line": 21, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 18 + }, + "1": { + "loc": { "start": { "line": 37, "column": 2 }, "end": { "line": 40, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 37, "column": 2 }, "end": { "line": 40, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 37 + }, + "2": { + "loc": { "start": { "line": 57, "column": 2 }, "end": { "line": 60, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 57, "column": 2 }, "end": { "line": 60, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 57 + }, + "3": { + "loc": { "start": { "line": 62, "column": 2 }, "end": { "line": 66, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 62, "column": 2 }, "end": { "line": 66, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 62 + }, + "4": { + "loc": { "start": { "line": 93, "column": 4 }, "end": { "line": 95, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 93, "column": 4 }, "end": { "line": 95, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 93 + }, + "5": { + "loc": { "start": { "line": 114, "column": 4 }, "end": { "line": 122, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 114, "column": 4 }, "end": { "line": 122, "column": null } }, + { "start": { "line": 120, "column": 11 }, "end": { "line": 122, "column": null } } + ], + "line": 114 + }, + "6": { + "loc": { "start": { "line": 115, "column": 6 }, "end": { "line": 117, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 115, "column": 6 }, "end": { "line": 117, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 115 + }, + "7": { + "loc": { "start": { "line": 125, "column": 2 }, "end": { "line": 127, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 125, "column": 2 }, "end": { "line": 127, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 125 + }, + "8": { + "loc": { "start": { "line": 135, "column": 4 }, "end": { "line": 135, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 135, "column": 4 }, "end": { "line": 135, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 135 + }, + "9": { + "loc": { "start": { "line": 135, "column": 8 }, "end": { "line": 135, "column": 50 } }, + "type": "binary-expr", + "locations": [ + { "start": { "line": 135, "column": 8 }, "end": { "line": 135, "column": 30 } }, + { "start": { "line": 135, "column": 30 }, "end": { "line": 135, "column": 50 } } + ], + "line": 135 + }, + "10": { + "loc": { "start": { "line": 147, "column": 2 }, "end": { "line": 147, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 147, "column": 2 }, "end": { "line": 147, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 147 + }, + "11": { + "loc": { "start": { "line": 151, "column": 2 }, "end": { "line": 151, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 151, "column": 2 }, "end": { "line": 151, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 151 + }, + "12": { + "loc": { "start": { "line": 156, "column": 2 }, "end": { "line": 161, "column": null } }, + "type": "if", + "locations": [ + { "start": { "line": 156, "column": 2 }, "end": { "line": 161, "column": null } }, + { "start": {}, "end": {} } + ], + "line": 156 + } + }, + "s": { + "0": 15, + "1": 2, + "2": 2, + "3": 13, + "4": 13, + "5": 13, + "6": 13, + "7": 13, + "8": 13, + "9": 13, + "10": 4, + "11": 4, + "12": 9, + "13": 9, + "14": 9, + "15": 13, + "16": 13, + "17": 13, + "18": 13, + "19": 13, + "20": 5, + "21": 5, + "22": 8, + "23": 4, + "24": 4, + "25": 4, + "26": 4, + "27": 4, + "28": 4, + "29": 4, + "30": 4, + "31": 13, + "32": 13, + "33": 13, + "34": 13, + "35": 24, + "36": 13, + "37": 13, + "38": 26, + "39": 26, + "40": 26, + "41": 26, + "42": 88, + "43": 88, + "44": 40, + "45": 18, + "46": 40, + "47": 40, + "48": 48, + "49": 26, + "50": 22, + "51": 26, + "52": 40, + "53": 62, + "54": 62, + "55": 40, + "56": 22, + "57": 40, + "58": 13, + "59": 13, + "60": 1, + "61": 12, + "62": 12, + "63": 12, + "64": 1, + "65": 11, + "66": 11, + "67": 11, + "68": 1, + "69": 10 + }, + "f": { "0": 15, "1": 13, "2": 13, "3": 13, "4": 26, "5": 40, "6": 13 }, + "b": { + "0": [2, 13], + "1": [4, 9], + "2": [5, 8], + "3": [4, 4], + "4": [13, 11], + "5": [40, 48], + "6": [18, 22], + "7": [22, 4], + "8": [40, 22], + "9": [62, 62], + "10": [1, 12], + "11": [1, 11], + "12": [1, 10] + }, + "meta": { + "lastBranch": 13, + "lastFunction": 7, + "lastStatement": 70, + "seen": { + "f:17:22:17:26": 0, + "b:18:2:21:Infinity:undefined:undefined:undefined:undefined": 0, + "s:18:2:21:Infinity": 0, + "s:19:4:19:Infinity": 1, + "s:20:4:20:Infinity": 2, + "s:23:19:23:Infinity": 3, + "s:24:2:24:Infinity": 4, + "s:26:2:26:Infinity": 5, + "s:27:2:27:Infinity": 6, + "s:28:2:28:Infinity": 7, + "f:35:9:35:22": 1, + "s:36:22:36:Infinity": 8, + "b:37:2:40:Infinity:undefined:undefined:undefined:undefined": 1, + "s:37:2:40:Infinity": 9, + "s:38:4:38:Infinity": 10, + "s:39:4:39:Infinity": 11, + "s:42:20:42:Infinity": 12, + "s:43:2:43:Infinity": 13, + "s:44:2:44:Infinity": 14, + "f:51:9:51:24": 2, + "s:52:19:52:Infinity": 15, + "s:53:17:53:Infinity": 16, + "s:54:21:54:Infinity": 17, + "s:55:19:55:Infinity": 18, + "b:57:2:60:Infinity:undefined:undefined:undefined:undefined": 2, + "s:57:2:60:Infinity": 19, + "s:58:4:58:Infinity": 20, + "s:59:4:59:Infinity": 21, + "b:62:2:66:Infinity:undefined:undefined:undefined:undefined": 3, + "s:62:2:66:Infinity": 22, + "s:63:4:63:Infinity": 23, + "s:64:4:64:Infinity": 24, + "s:65:4:65:Infinity": 25, + "s:68:2:68:Infinity": 26, + "s:69:22:69:Infinity": 27, + "s:70:20:70:Infinity": 28, + "s:71:17:71:Infinity": 29, + "s:72:2:72:Infinity": 30, + "f:87:16:87:39": 3, + "s:88:24:88:Infinity": 31, + "s:89:26:89:Infinity": 32, + "s:91:17:91:Infinity": 33, + "s:92:2:96:Infinity": 34, + "b:93:4:95:Infinity:undefined:undefined:undefined:undefined": 4, + "s:93:4:95:Infinity": 35, + "s:94:6:94:Infinity": 36, + "s:98:2:98:Infinity": 37, + "f:107:9:107:29": 4, + "s:108:17:108:Infinity": 38, + "s:109:19:109:Infinity": 39, + "s:110:31:110:Infinity": 40, + "s:112:2:123:Infinity": 41, + "s:113:18:113:Infinity": 42, + "b:114:4:122:Infinity:120:11:122:Infinity": 5, + "s:114:4:122:Infinity": 43, + "b:115:6:117:Infinity:undefined:undefined:undefined:undefined": 6, + "s:115:6:117:Infinity": 44, + "s:116:8:116:Infinity": 45, + "s:118:6:118:Infinity": 46, + "s:119:6:119:Infinity": 47, + "s:121:6:121:Infinity": 48, + "b:125:2:127:Infinity:undefined:undefined:undefined:undefined": 7, + "s:125:2:127:Infinity": 49, + "s:126:4:126:Infinity": 50, + "s:129:2:129:Infinity": 51, + "f:132:9:132:28": 5, + "s:133:2:137:Infinity": 52, + "s:134:17:134:Infinity": 53, + "b:135:4:135:Infinity:undefined:undefined:undefined:undefined": 8, + "s:135:4:135:Infinity": 54, + "b:135:8:135:30:135:30:135:50": 9, + "s:135:50:135:Infinity": 55, + "s:136:4:136:Infinity": 56, + "s:138:2:138:Infinity": 57, + "f:145:9:145:26": 6, + "s:146:21:146:Infinity": 58, + "b:147:2:147:Infinity:undefined:undefined:undefined:undefined": 10, + "s:147:2:147:Infinity": 59, + "s:147:34:147:Infinity": 60, + "s:149:18:149:Infinity": 61, + "s:150:16:150:Infinity": 62, + "b:151:2:151:Infinity:undefined:undefined:undefined:undefined": 11, + "s:151:2:151:Infinity": 63, + "s:151:32:151:Infinity": 64, + "s:153:19:153:Infinity": 65, + "s:154:19:154:Infinity": 66, + "b:156:2:161:Infinity:undefined:undefined:undefined:undefined": 12, + "s:156:2:161:Infinity": 67, + "s:157:4:160:Infinity": 68, + "s:163:2:163:Infinity": 69 + }, + "fnNames": {} + } + } +} diff --git a/prepare-sources/lib/modules.ts b/prepare-sources/lib/modules.ts index 361477f..1a25e9d 100644 --- a/prepare-sources/lib/modules.ts +++ b/prepare-sources/lib/modules.ts @@ -4,6 +4,7 @@ import { run as makeSelfContained } from "./modules/make-self-contained/index.ts import { run as generateManifests } from "./modules/generate-manifests/index.ts"; import { run as pluginRemoval } from "./modules/plugin-removal/index.ts"; import { run as fileCleanup } from "./modules/file-cleanup/index.ts"; +import { run as protocolResolution } from "./modules/protocol-resolution/index.ts"; async function notImplemented(ctx: ModuleContext): Promise { ctx.log("not yet implemented"); @@ -16,7 +17,7 @@ export const MODULES: readonly PipelineModule[] = [ { name: "generate-manifests", run: generateManifests }, { name: "plugin-removal", run: pluginRemoval }, { name: "file-cleanup", run: fileCleanup }, - { name: "protocol-resolution", run: notImplemented }, + { name: "protocol-resolution", run: protocolResolution }, { name: "package-cleanup", run: notImplemented }, { name: "hermetic-prep", run: hermeticPrep }, { name: "inject-build-tools", run: notImplemented }, diff --git a/prepare-sources/lib/modules/file-cleanup/DESIGN.md b/prepare-sources/lib/modules/file-cleanup/DESIGN.md new file mode 100644 index 0000000..6c0779c --- /dev/null +++ b/prepare-sources/lib/modules/file-cleanup/DESIGN.md @@ -0,0 +1,52 @@ +# file-cleanup — design (grill session) + +## Scope + +Remove development-only files and directories from surviving workspace packages after `plugin-removal`. Does not change workspace structure — only deletes matching paths within the workspace tree. + +## Source of truth + +`sync-midstream.sh` lines 917–924 (the `find` + `rm` block). Match that behavior exactly; do not add patterns from the design-decisions summary table (`*.stories.*`, `*.mock.*`) unless they appear in bash. + +## Removable paths + +**Directories** (entire tree removed when the directory name matches): + +- `dev` +- `e2e-tests` +- `__tests__` +- `__mocks__` + +**Files** (basename match): + +- `*.test.ts` +- `*.test.tsx` +- `*.spec.ts` +- `*.spec.tsx` + +## Exclusions + +Skip any path whose relative path contains: + +- `/node_modules/` +- `/dist-dynamic/` + +Same as bash `-not -path "*/node_modules/*" -not -path "*/dist-dynamic/*"`. + +## Algorithm + +1. Walk the workspace recursively from `ctx.workspacePath`. +2. Collect removable directory paths (name match, not under excluded segments). +3. Sort directories by depth descending; `rm -rf` each (deepest first avoids redundant work). +4. Walk again (or single walk with skip-under-removed); collect removable files not under excluded segments. +5. Delete files; log each removal via `ctx.log`. + +## Non-goals + +- No overlay reads (`plugins-list.yaml`, tier lists). +- No package.json or lockfile changes. +- No infrastructure or plugin directory removal (handled by `plugin-removal`). + +## Pipeline position + +After `plugin-removal`, before `protocol-resolution`. diff --git a/prepare-sources/lib/modules/protocol-resolution/DESIGN.md b/prepare-sources/lib/modules/protocol-resolution/DESIGN.md new file mode 100644 index 0000000..c519582 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/DESIGN.md @@ -0,0 +1,82 @@ +# protocol-resolution — design (grill-with-docs) + +Pre-implementation design for RHIDP-15838. **Implement against this document**; keep `README.md` as the post-implementation module guide. + +Related: `docs/source-preparation-design-decisions.md` §4, §11. + +--- + +## Language + +**Protocol reference:** +A `package.json` or `yarn.lock` dependency specifier using `workspace:^`, `workspace:*`, `workspace:~`, or `backstage:^`. +_Avoid_: monorepo ref (too vague). + +**Surviving local package:** +A workspace package whose directory still exists on disk after `plugin-removal`. Keeps `workspace:^` references in `package.json` and `yarn.lock` so `rhdh-cli` can resolve them during re-export. +_Avoid_: exported plugin (export is a later step). + +**Scrubbed package:** +A package listed in `manifest.json` whose source directory was removed by `plugin-removal`. Protocol references to scrubbed packages are resolved to concrete npm semver ranges. +_Avoid_: deleted package (ambiguous with `package-cleanup` lockfile deletion). + +**Version map:** +`Map` built from `manifest.json` and `backstage-manifest.json` (generated before scrubbing). Authoritative for resolving protocol references. +_Avoid_: version manifest (collides with manifest.json naming). + +**Type-shims package:** +`@internal/type-shims` at `packages/type-shims/` — aggregates host deps (`react`, etc.) and `@types/*` from scrubbed packages needed by surviving code. Pre-wired in `yarn.lock` as `linkType: soft`. +_Avoid_: stub package (old per-package approach). + +## Relationships + +- **protocol-resolution** runs after `generate-manifests`, `plugin-removal`, and `file-cleanup` +- Reads `manifest.json` (+ `backstage-manifest.json` when present) written before scrubbing +- Equivalent to `update-workspace.js --update` plus the `createTypeShimsPackage` portion of `--delete` (physical deletion already done by `plugin-removal`; lockfile entry deletion is `package-cleanup`) +- `package-cleanup` runs next and removes scrubbed package lockfile blocks + +## Resolved decisions + +### 1. Scope = `--update` + type-shims only + +Implement protocol reference resolution in `package.json` and `yarn.lock`, plus `packages/type-shims/` creation. Do **not** implement `--delete` lockfile scrubbing or `--remove-patches` — those are `package-cleanup`. + +### 2. Preserve `workspace:^` for surviving local packages + +Match `replaceWorkspaceReferences`: if `findPackageVersion(name)` finds a local `package.json`, skip conversion in `package.json`. In `yarn.lock`, local packages get combined-key normalization only — no npm block replacement. + +### 3. Manifest-driven version map + +Build version map from workspace + backstage manifests on disk. No `--version-map` CLI flag; manifests are the sole source (generated by `generate-manifests` in the same pipeline run). + +### 4. npm metadata via `fetch` + +When creating missing resolution blocks, fetch npm registry metadata with `fetch` (retries for transient errors). Prefer backstage-manifest entries when available. + +### 5. `yarn.lock` processed once per workspace + +Process all `package.json` files but run the full `yarn.lock` transformation only once (first file triggers it), matching the original single-pass semantics. + +### 6. Type-shims timing + +Create type-shims after `yarn.lock` rewrite. Analyze scrubbed packages via manifest entries whose `path` directory no longer exists. Skip creation when nothing is needed. + +## Algorithm (implementation contract) + +1. Load `manifest.json`; load `backstage-manifest.json` if present. +2. Build version map (workspace packages first, backstage packages fill gaps). +3. Discover all workspace `package.json` files (same ignore dirs as `generate-manifests`). +4. For each `package.json`: replace protocol refs in dependency sections; write if changed. +5. Once: parse `yarn.lock` via shared `yarn-lock-parser`, mutate the `Lockfile` structure, serialize back (delete stale/non-local workspace blocks, convert dep refs, recreate npm blocks, dangling-dep passes, enrich specifiers). +6. Create `packages/type-shims/` when needed; update root `package.json` workspaces and `tsconfig.json` references; pre-wire lockfile entry. +7. Throw on unrecoverable yarn.lock inconsistencies or npm metadata failures for required blocks. + +## Error handling + +- Missing `manifest.json` → throw (required input). +- Missing `yarn.lock` at workspace root → throw. +- `createMissingResolutionBlocks` npm fetch failures or soft-link inconsistencies → throw with package list. + +## Pipeline position + +After `file-cleanup`, before `package-cleanup`. diff --git a/prepare-sources/lib/modules/protocol-resolution/README.md b/prepare-sources/lib/modules/protocol-resolution/README.md new file mode 100644 index 0000000..f02e826 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/README.md @@ -0,0 +1,64 @@ +# protocol-resolution + +Resolves `workspace:^` and `backstage:^` protocol references to concrete npm +semver ranges so the prepared workspace can build without the upstream monorepo. +Also creates `packages/type-shims` when surviving code needs types from scrubbed +packages. + +## Pipeline position + +After `file-cleanup`, before `package-cleanup`. + +## Inputs + +| Path | Description | +| ------------------------- | ------------------------------------------------------------------ | +| `manifest.json` | Workspace package inventory (from `generate-manifests`, pre-scrub) | +| `backstage-manifest.json` | Backstage release packages (optional) | +| `package.json` files | All workspace packages | +| `yarn.lock` | Workspace lockfile | +| `tsconfig.json` | Root TypeScript config (for type-shims references) | + +## Outputs + +| Path | Description | +| ---------------------- | --------------------------------------------------------------------------------------------------- | +| `package.json` files | Protocol refs resolved to `^version` for scrubbed packages; surviving local `workspace:^` preserved | +| `yarn.lock` | Workspace blocks replaced with npm blocks; dangling deps wired; specifiers enriched | +| `packages/type-shims/` | Aggregated host deps and `@types/*` when needed | +| Root `package.json` | `packages/type-shims` added to workspaces | +| Root `tsconfig.json` | Reference to `packages/type-shims` | + +## Behavior + +**Surviving local packages** keep `workspace:^` in `package.json` so `rhdh-cli` +can resolve them during re-export. Only references to scrubbed packages (no +longer on disk) are converted to npm ranges. + +**yarn.lock transformation** uses the shared `yarn-lock-parser` (`parseLockfile` / +`serializeLockfile`) and `yarn-lock-helpers` utilities. It deletes stale +workspace-path blocks for removed directories, converts non-local `workspace:^` / +`backstage:^` blocks to npm resolution blocks (using manifest or registry +metadata), runs dangling-dependency passes, and enriches combined block keys. + +**type-shims** aggregates `react`/`react-dom` host deps from scrubbed `app` +packages and needed `@types/*` from scrubbed devDependencies. Skipped when +nothing is required. + +## Errors + +- Missing `manifest.json` or `yarn.lock` +- Cannot fetch npm metadata for a package that needs a new resolution block +- Surviving `linkType: soft` blocks keyed as npm (inconsistent lockfile) + +## Tests + +Fixture-based I/O tests under `__fixtures__/`. Each subdirectory name is the +Vitest case title; see the fixture catalog comment in `index.test.ts`. + +Scenarios cover package.json protocol resolution, yarn.lock block lifecycle +(stale paths, combined keys for local packages, specifier enrichment, dangling +deps), type-shims +creation, no-op paths, and error cases. Scrubbed packages in `manifest.json` +should include `dependencies` (even `{}`) so resolution blocks can be built +without registry fetches. diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/manifest.json new file mode 100644 index 0000000..30bc81f --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/manifest.json @@ -0,0 +1,22 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/shared", + "version": "1.0.0", + "path": "plugins/shared/package.json" + }, + { + "name": "@local/consumer", + "version": "1.0.0", + "path": "plugins/consumer/package.json", + "dependencies": { + "@local/shared": "workspace:^" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/plugins/consumer/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/plugins/consumer/package.json new file mode 100644 index 0000000..2524aea --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/plugins/consumer/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/consumer", + "version": "1.0.0", + "private": true, + "dependencies": { + "@local/shared": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/plugins/shared/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/plugins/shared/package.json new file mode 100644 index 0000000..8a66c5e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/plugins/shared/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/shared", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/yarn.lock new file mode 100644 index 0000000..df264c3 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/input/workspace/yarn.lock @@ -0,0 +1,16 @@ +__metadata: + version: 8 + +"@local/shared@workspace:plugins/shared": + version: 0.0.0-use.local + resolution: "@local/shared@workspace:plugins/shared" + languageName: unknown + linkType: soft + +"@local/consumer@workspace:plugins/consumer": + version: 0.0.0-use.local + resolution: "@local/consumer@workspace:plugins/consumer" + dependencies: + "@local/shared": "npm:^1.0.0" + languageName: unknown + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/manifest.json new file mode 100644 index 0000000..30bc81f --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/manifest.json @@ -0,0 +1,22 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/shared", + "version": "1.0.0", + "path": "plugins/shared/package.json" + }, + { + "name": "@local/consumer", + "version": "1.0.0", + "path": "plugins/consumer/package.json", + "dependencies": { + "@local/shared": "workspace:^" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/plugins/consumer/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/plugins/consumer/package.json new file mode 100644 index 0000000..2524aea --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/plugins/consumer/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/consumer", + "version": "1.0.0", + "private": true, + "dependencies": { + "@local/shared": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/plugins/shared/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/plugins/shared/package.json new file mode 100644 index 0000000..8a66c5e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/plugins/shared/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/shared", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/yarn.lock new file mode 100644 index 0000000..8cd2bfe --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-combined-key-for-local-with-npm-refs/output/workspace/yarn.lock @@ -0,0 +1,30 @@ +__metadata: + version: 8 + +"@local/shared@workspace:plugins/shared": + version: 0.0.0-use.local + resolution: "@local/shared@workspace:plugins/shared" + languageName: unknown + linkType: soft + +"@local/consumer@workspace:plugins/consumer": + version: 0.0.0-use.local + resolution: "@local/consumer@workspace:plugins/consumer" + dependencies: + "@local/shared": "npm:^1.0.0" + languageName: unknown + linkType: soft + +"@local/shared@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/shared@npm:1.0.0" + languageName: node + linkType: hard + +"@local/consumer@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/consumer@npm:1.0.0" + dependencies: + "@local/shared": "npm:^1.0.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/overlay/source.json new file mode 100644 index 0000000..8b08042 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/test/test", + "repo-ref": "v1.0.0", + "repo-flat": false, + "repo-backstage-version": "1.45.0" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/manifest.json new file mode 100644 index 0000000..0e2ae83 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/manifest.json @@ -0,0 +1,40 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "@backstage/core-plugin-api": "^1.9.0", + "@internal/my-lib": "^2.0.0" + } + }, + { + "name": "@internal/my-lib", + "version": "2.0.0", + "path": "packages/my-lib/package.json", + "dependencies": { + "@backstage/types": "^1.0.0" + } + }, + { + "name": "@backstage/core-plugin-api", + "version": "1.9.0", + "path": "packages/core-plugin-api/package.json", + "dependencies": { + "@internal/my-lib": "^2.0.0" + } + }, + { + "name": "@backstage/types", + "version": "1.0.0", + "path": "packages/types/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/package.json new file mode 100644 index 0000000..441e057 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/package.json @@ -0,0 +1,6 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": ["plugins/*", "packages/*"] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/packages/my-lib/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/packages/my-lib/package.json new file mode 100644 index 0000000..22d8537 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/packages/my-lib/package.json @@ -0,0 +1,7 @@ +{ + "name": "@internal/my-lib", + "version": "2.0.0", + "dependencies": { + "@backstage/types": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..6272e39 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "dependencies": { + "@backstage/core-plugin-api": "workspace:^", + "@internal/my-lib": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/yarn.lock new file mode 100644 index 0000000..3275992 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/input/workspace/yarn.lock @@ -0,0 +1,33 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + "@backstage/core-plugin-api": "workspace:^" + "@internal/my-lib": "workspace:^" + languageName: unknown + linkType: soft + +"@internal/my-lib@workspace:packages/my-lib": + version: 0.0.0-use.local + resolution: "@internal/my-lib@workspace:packages/my-lib" + dependencies: + "@backstage/types": "workspace:^" + languageName: unknown + linkType: soft + +"@backstage/core-plugin-api@workspace:^": + version: 0.0.0-use.local + resolution: "@backstage/core-plugin-api@workspace:packages/core-plugin-api" + dependencies: + "@internal/my-lib": "npm:^2.0.0" + languageName: unknown + linkType: soft + +"@backstage/types@workspace:^": + version: 0.0.0-use.local + resolution: "@backstage/types@workspace:packages/types" + languageName: unknown + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/manifest.json new file mode 100644 index 0000000..0e2ae83 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/manifest.json @@ -0,0 +1,40 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "@backstage/core-plugin-api": "^1.9.0", + "@internal/my-lib": "^2.0.0" + } + }, + { + "name": "@internal/my-lib", + "version": "2.0.0", + "path": "packages/my-lib/package.json", + "dependencies": { + "@backstage/types": "^1.0.0" + } + }, + { + "name": "@backstage/core-plugin-api", + "version": "1.9.0", + "path": "packages/core-plugin-api/package.json", + "dependencies": { + "@internal/my-lib": "^2.0.0" + } + }, + { + "name": "@backstage/types", + "version": "1.0.0", + "path": "packages/types/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/package.json new file mode 100644 index 0000000..441e057 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/package.json @@ -0,0 +1,6 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": ["plugins/*", "packages/*"] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/packages/my-lib/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/packages/my-lib/package.json new file mode 100644 index 0000000..aa13995 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/packages/my-lib/package.json @@ -0,0 +1,7 @@ +{ + "name": "@internal/my-lib", + "version": "2.0.0", + "dependencies": { + "@backstage/types": "^1.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..a5d7379 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "dependencies": { + "@backstage/core-plugin-api": "^1.9.0", + "@internal/my-lib": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/yarn.lock new file mode 100644 index 0000000..d0b3003 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-hard-npm-blocks-for-local-packages/output/workspace/yarn.lock @@ -0,0 +1,50 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + "@backstage/core-plugin-api": "npm:^1.9.0" + "@internal/my-lib": "workspace:^" + languageName: unknown + linkType: soft + +"@internal/my-lib@workspace:packages/my-lib": + version: 0.0.0-use.local + resolution: "@internal/my-lib@workspace:packages/my-lib" + dependencies: + "@backstage/types": "npm:^1.0.0" + languageName: unknown + linkType: soft + +"@backstage/core-plugin-api@npm:^1.9.0": + version: 1.9.0 + resolution: "@backstage/core-plugin-api@npm:1.9.0" + dependencies: + "@internal/my-lib": "npm:^2.0.0" + languageName: node + linkType: hard + +"@backstage/types@npm:^1.0.0": + version: 1.0.0 + resolution: "@backstage/types@npm:1.0.0" + languageName: node + linkType: hard + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + dependencies: + "@backstage/core-plugin-api": "npm:^1.9.0" + "@internal/my-lib": "npm:^2.0.0" + languageName: node + linkType: hard + +"@internal/my-lib@npm:^2.0.0": + version: 2.0.0 + resolution: "@internal/my-lib@npm:2.0.0" + dependencies: + "@backstage/types": "npm:^1.0.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/manifest.json new file mode 100644 index 0000000..d8fcea9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/package.json new file mode 100644 index 0000000..7ede9ca --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/package.json @@ -0,0 +1,9 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..360fe52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,3 @@ +import React from "react"; + +export const Page = () =>
hello
; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/tsconfig.json new file mode 100644 index 0000000..0cd97e0 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/yarn.lock new file mode 100644 index 0000000..25edc8a --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/input/workspace/yarn.lock @@ -0,0 +1,15 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/manifest.json new file mode 100644 index 0000000..d8fcea9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/package.json new file mode 100644 index 0000000..ed68a52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/package.json @@ -0,0 +1,10 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*", + "packages/type-shims" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/packages/type-shims/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/packages/type-shims/package.json new file mode 100644 index 0000000..dea6f29 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/packages/type-shims/package.json @@ -0,0 +1,12 @@ +{ + "name": "@internal/type-shims", + "version": "0.0.0-use.local", + "private": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/packages/type-shims/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/packages/type-shims/tsconfig.json new file mode 100644 index 0000000..9bac71e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/packages/type-shims/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true + }, + "include": [ + "src" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..360fe52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,3 @@ +import React from "react"; + +export const Page = () =>
hello
; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/tsconfig.json new file mode 100644 index 0000000..29f9497 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [ + { + "path": "packages/type-shims" + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/yarn.lock new file mode 100644 index 0000000..cb6a81c --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-from-scrubbed-app/output/workspace/yarn.lock @@ -0,0 +1,34 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard + +"@local/frontend@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/frontend@npm:1.0.0" + dependencies: + "react": "npm:^18.0.0" + languageName: node + linkType: hard + +"@internal/type-shims@workspace:packages/type-shims": + version: 0.0.0-use.local + resolution: "@internal/type-shims@workspace:packages/type-shims" + languageName: unknown + linkType: soft + dependencies: + "react-dom": "npm:^18.2.0" + "react": "npm:^18.2.0" + devDependencies: + "@types/react": "npm:^18.0.0" diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/manifest.json new file mode 100644 index 0000000..d8fcea9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/package.json new file mode 100644 index 0000000..7ede9ca --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/package.json @@ -0,0 +1,9 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..866e9c7 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,4 @@ +import React from "react"; +import "./styles.module.css"; + +export const Page = () =>
hello
; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/tsconfig.json new file mode 100644 index 0000000..0cd97e0 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/yarn.lock new file mode 100644 index 0000000..25edc8a --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/input/workspace/yarn.lock @@ -0,0 +1,15 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/manifest.json new file mode 100644 index 0000000..d8fcea9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/package.json new file mode 100644 index 0000000..ed68a52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/package.json @@ -0,0 +1,10 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*", + "packages/type-shims" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/package.json new file mode 100644 index 0000000..dea6f29 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/package.json @@ -0,0 +1,12 @@ +{ + "name": "@internal/type-shims", + "version": "0.0.0-use.local", + "private": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/src/global-augments.d.ts b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/src/global-augments.d.ts new file mode 100644 index 0000000..e4ff2eb --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/src/global-augments.d.ts @@ -0,0 +1 @@ +import '@backstage/cli/asset-types'; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/tsconfig.json new file mode 100644 index 0000000..9bac71e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/packages/type-shims/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true + }, + "include": [ + "src" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..866e9c7 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,4 @@ +import React from "react"; +import "./styles.module.css"; + +export const Page = () =>
hello
; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/tsconfig.json new file mode 100644 index 0000000..29f9497 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [ + { + "path": "packages/type-shims" + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/yarn.lock new file mode 100644 index 0000000..cb6a81c --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-asset-types/output/workspace/yarn.lock @@ -0,0 +1,34 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard + +"@local/frontend@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/frontend@npm:1.0.0" + dependencies: + "react": "npm:^18.0.0" + languageName: node + linkType: hard + +"@internal/type-shims@workspace:packages/type-shims": + version: 0.0.0-use.local + resolution: "@internal/type-shims@workspace:packages/type-shims" + languageName: unknown + linkType: soft + dependencies: + "react-dom": "npm:^18.2.0" + "react": "npm:^18.2.0" + devDependencies: + "@types/react": "npm:^18.0.0" diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/manifest.json new file mode 100644 index 0000000..f1f06fb --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/manifest.json @@ -0,0 +1,30 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0", + "@types/compression": "^1.7.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/package.json new file mode 100644 index 0000000..7ede9ca --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/package.json @@ -0,0 +1,9 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..360fe52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,3 @@ +import React from "react"; + +export const Page = () =>
hello
; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/tsconfig.json new file mode 100644 index 0000000..0cd97e0 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/yarn.lock new file mode 100644 index 0000000..25edc8a --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/input/workspace/yarn.lock @@ -0,0 +1,15 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/manifest.json new file mode 100644 index 0000000..f1f06fb --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/manifest.json @@ -0,0 +1,30 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0", + "@types/compression": "^1.7.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/package.json new file mode 100644 index 0000000..ed68a52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/package.json @@ -0,0 +1,10 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*", + "packages/type-shims" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/package.json new file mode 100644 index 0000000..9dff07d --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/package.json @@ -0,0 +1,13 @@ +{ + "name": "@internal/type-shims", + "version": "0.0.0-use.local", + "private": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0", + "@types/compression": "^1.7.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/src/global-augments.d.ts b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/src/global-augments.d.ts new file mode 100644 index 0000000..2a6b1b9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/src/global-augments.d.ts @@ -0,0 +1 @@ +import 'compression'; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/tsconfig.json new file mode 100644 index 0000000..9bac71e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/packages/type-shims/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true + }, + "include": [ + "src" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..360fe52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,3 @@ +import React from "react"; + +export const Page = () =>
hello
; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/tsconfig.json new file mode 100644 index 0000000..29f9497 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [ + { + "path": "packages/type-shims" + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/yarn.lock new file mode 100644 index 0000000..3a4a892 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-extra-runtime-types/output/workspace/yarn.lock @@ -0,0 +1,35 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard + +"@local/frontend@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/frontend@npm:1.0.0" + dependencies: + "react": "npm:^18.0.0" + languageName: node + linkType: hard + +"@internal/type-shims@workspace:packages/type-shims": + version: 0.0.0-use.local + resolution: "@internal/type-shims@workspace:packages/type-shims" + languageName: unknown + linkType: soft + dependencies: + "react-dom": "npm:^18.2.0" + "react": "npm:^18.2.0" + devDependencies: + "@types/compression": "npm:^1.7.0" + "@types/react": "npm:^18.0.0" diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/manifest.json new file mode 100644 index 0000000..d8fcea9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/package.json new file mode 100644 index 0000000..7ede9ca --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/package.json @@ -0,0 +1,9 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..a61a77b --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,9 @@ +import React from "react"; +import { makeStyles } from "@mui/styles"; + +const useStyles = makeStyles({ root: { color: "red" } }); + +export const Page = () => { + const classes = useStyles(); + return
hello
; +}; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/tsconfig.json new file mode 100644 index 0000000..0cd97e0 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/yarn.lock new file mode 100644 index 0000000..25edc8a --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/input/workspace/yarn.lock @@ -0,0 +1,15 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/manifest.json new file mode 100644 index 0000000..d8fcea9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/package.json new file mode 100644 index 0000000..ed68a52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/package.json @@ -0,0 +1,10 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*", + "packages/type-shims" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/package.json new file mode 100644 index 0000000..dea6f29 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/package.json @@ -0,0 +1,12 @@ +{ + "name": "@internal/type-shims", + "version": "0.0.0-use.local", + "private": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/src/global-augments.d.ts b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/src/global-augments.d.ts new file mode 100644 index 0000000..8a26f02 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/src/global-augments.d.ts @@ -0,0 +1 @@ +import '@backstage/theme'; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/tsconfig.json new file mode 100644 index 0000000..9bac71e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/packages/type-shims/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true + }, + "include": [ + "src" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..a61a77b --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,9 @@ +import React from "react"; +import { makeStyles } from "@mui/styles"; + +const useStyles = makeStyles({ root: { color: "red" } }); + +export const Page = () => { + const classes = useStyles(); + return
hello
; +}; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/tsconfig.json new file mode 100644 index 0000000..29f9497 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [ + { + "path": "packages/type-shims" + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/yarn.lock new file mode 100644 index 0000000..cb6a81c --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-theme-augmentation/output/workspace/yarn.lock @@ -0,0 +1,34 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard + +"@local/frontend@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/frontend@npm:1.0.0" + dependencies: + "react": "npm:^18.0.0" + languageName: node + linkType: hard + +"@internal/type-shims@workspace:packages/type-shims": + version: 0.0.0-use.local + resolution: "@internal/type-shims@workspace:packages/type-shims" + languageName: unknown + linkType: soft + dependencies: + "react-dom": "npm:^18.2.0" + "react": "npm:^18.2.0" + devDependencies: + "@types/react": "npm:^18.0.0" diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/manifest.json new file mode 100644 index 0000000..d8fcea9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/package.json new file mode 100644 index 0000000..5dc211e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/package.json @@ -0,0 +1,11 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": { + "packages": [ + "plugins/*", + "packages/*" + ] + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..360fe52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,3 @@ +import React from "react"; + +export const Page = () =>
hello
; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/tsconfig.json new file mode 100644 index 0000000..0cd97e0 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/yarn.lock new file mode 100644 index 0000000..25edc8a --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/input/workspace/yarn.lock @@ -0,0 +1,15 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/manifest.json new file mode 100644 index 0000000..d8fcea9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/frontend", + "version": "1.0.0", + "path": "plugins/frontend/package.json", + "dependencies": { + "react": "^18.0.0" + } + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/package.json new file mode 100644 index 0000000..476a395 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/package.json @@ -0,0 +1,12 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": { + "packages": [ + "plugins/*", + "packages/*", + "packages/type-shims" + ] + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/packages/type-shims/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/packages/type-shims/package.json new file mode 100644 index 0000000..dea6f29 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/packages/type-shims/package.json @@ -0,0 +1,12 @@ +{ + "name": "@internal/type-shims", + "version": "0.0.0-use.local", + "private": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/packages/type-shims/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/packages/type-shims/tsconfig.json new file mode 100644 index 0000000..9bac71e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/packages/type-shims/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true + }, + "include": [ + "src" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/plugins/frontend/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/plugins/frontend/package.json new file mode 100644 index 0000000..5e08fd9 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/plugins/frontend/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/frontend", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/plugins/frontend/src/index.tsx b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/plugins/frontend/src/index.tsx new file mode 100644 index 0000000..360fe52 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/plugins/frontend/src/index.tsx @@ -0,0 +1,3 @@ +import React from "react"; + +export const Page = () =>
hello
; diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/tsconfig.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/tsconfig.json new file mode 100644 index 0000000..29f9497 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES2022" + }, + "references": [ + { + "path": "packages/type-shims" + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/yarn.lock new file mode 100644 index 0000000..cb6a81c --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/creates-type-shims-with-workspaces-object/output/workspace/yarn.lock @@ -0,0 +1,34 @@ +__metadata: + version: 8 + +"@local/frontend@workspace:plugins/frontend": + version: 0.0.0-use.local + resolution: "@local/frontend@workspace:plugins/frontend" + dependencies: + react: "npm:^18.0.0" + languageName: unknown + linkType: soft + +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + linkType: hard + +"@local/frontend@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/frontend@npm:1.0.0" + dependencies: + "react": "npm:^18.0.0" + languageName: node + linkType: hard + +"@internal/type-shims@workspace:packages/type-shims": + version: 0.0.0-use.local + resolution: "@internal/type-shims@workspace:packages/type-shims" + languageName: unknown + linkType: soft + dependencies: + "react-dom": "npm:^18.2.0" + "react": "npm:^18.2.0" + devDependencies: + "@types/react": "npm:^18.0.0" diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/manifest.json new file mode 100644 index 0000000..4aaf3dd --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/manifest.json @@ -0,0 +1,20 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json" + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/package.json new file mode 100644 index 0000000..7ede9ca --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/package.json @@ -0,0 +1,9 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..8599edf --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/plugins/plugin/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/yarn.lock new file mode 100644 index 0000000..3f29cf5 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/input/workspace/yarn.lock @@ -0,0 +1,20 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + languageName: unknown + linkType: soft + +"@internal/app@workspace:packages/app": + version: 0.0.0-use.local + resolution: "@internal/app@workspace:packages/app" + languageName: unknown + linkType: soft + +"@internal/app@workspace:^": + version: 0.0.0 + resolution: "@internal/app@workspace:^" + languageName: node + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/manifest.json new file mode 100644 index 0000000..4aaf3dd --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/manifest.json @@ -0,0 +1,20 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json" + }, + { + "name": "@internal/app", + "version": "0.0.0", + "path": "packages/app/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/package.json new file mode 100644 index 0000000..7ede9ca --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/package.json @@ -0,0 +1,9 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*", + "packages/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..8599edf --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/plugins/plugin/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/yarn.lock new file mode 100644 index 0000000..7822046 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/deletes-stale-workspace-path-lockfile-blocks/output/workspace/yarn.lock @@ -0,0 +1,14 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + languageName: unknown + linkType: soft + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/overlay/source.json new file mode 100644 index 0000000..8b08042 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/test/test", + "repo-ref": "v1.0.0", + "repo-flat": false, + "repo-backstage-version": "1.45.0" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/manifest.json new file mode 100644 index 0000000..133afe1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/manifest.json @@ -0,0 +1,17 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "lodash": "^4.17.21" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/package.json new file mode 100644 index 0000000..c3b64fc --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/package.json @@ -0,0 +1,6 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": ["plugins/*"] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..f52e8c0 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/plugins/plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/yarn.lock new file mode 100644 index 0000000..3ff737c --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/input/workspace/yarn.lock @@ -0,0 +1,22 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + lodash: "npm:^4.17.21" + languageName: unknown + linkType: soft + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + dependencies: + "ms": "npm:^2.1.3" + linkType: hard + +"ms@npm:^2.1.0": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/manifest.json new file mode 100644 index 0000000..133afe1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/manifest.json @@ -0,0 +1,17 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "lodash": "^4.17.21" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/package.json new file mode 100644 index 0000000..c3b64fc --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/package.json @@ -0,0 +1,6 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": ["plugins/*"] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..f52e8c0 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/plugins/plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/yarn.lock new file mode 100644 index 0000000..1a37478 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/enriches-npm-block-specifiers/output/workspace/yarn.lock @@ -0,0 +1,30 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + lodash: "npm:^4.17.21" + languageName: unknown + linkType: soft + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + dependencies: + "ms": "npm:^2.1.3" + linkType: hard + +"ms@npm:^2.1.0, ms@npm:^2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + linkType: hard + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + dependencies: + "lodash": "npm:^4.17.21" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/overlay/source.json new file mode 100644 index 0000000..189d505 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/overlay/source.json @@ -0,0 +1 @@ +{"repo":"https://github.com/example/repo","repo-ref":"abc123","repo-flat":false,"repo-backstage-version":"1.45.1"} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/manifest.json new file mode 100644 index 0000000..685feeb --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/manifest.json @@ -0,0 +1,22 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "scrubbed-lib": "workspace:^" + } + }, + { + "name": "scrubbed-lib", + "version": "2.0.0", + "path": "packages/lib/package.json" + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..ddff547 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "scrubbed-lib": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/yarn.lock new file mode 100644 index 0000000..fac85bb --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/input/workspace/yarn.lock @@ -0,0 +1,16 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + scrubbed-lib: "workspace:^" + languageName: unknown + linkType: soft + +"scrubbed-lib@workspace:^": + version: 2.0.0 + resolution: "scrubbed-lib@workspace:^" + languageName: node + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/npm-responses/scrubbed-lib@2.0.0.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/npm-responses/scrubbed-lib@2.0.0.json new file mode 100644 index 0000000..7bc94f2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/npm-responses/scrubbed-lib@2.0.0.json @@ -0,0 +1,7 @@ +{ + "name": "scrubbed-lib", + "version": "2.0.0", + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/manifest.json new file mode 100644 index 0000000..685feeb --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/manifest.json @@ -0,0 +1,22 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "scrubbed-lib": "workspace:^" + } + }, + { + "name": "scrubbed-lib", + "version": "2.0.0", + "path": "packages/lib/package.json" + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..ae6d3af --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "scrubbed-lib": "^2.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/yarn.lock new file mode 100644 index 0000000..2ec4ce8 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/falls-back-to-npm-for-missing-manifest-deps/output/workspace/yarn.lock @@ -0,0 +1,26 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + scrubbed-lib: "npm:^2.0.0" + languageName: unknown + linkType: soft + +"scrubbed-lib@npm:^2.0.0": + version: 2.0.0 + resolution: "scrubbed-lib@npm:2.0.0" + dependencies: + "lodash": "npm:^4.17.21" + languageName: node + linkType: hard + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + dependencies: + "scrubbed-lib": "npm:^2.0.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/manifest.json new file mode 100644 index 0000000..133afe1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/manifest.json @@ -0,0 +1,17 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "lodash": "^4.17.21" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..70755f1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/yarn.lock new file mode 100644 index 0000000..6c9b589 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/input/workspace/yarn.lock @@ -0,0 +1,15 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + lodash: "npm:^4.17.21" + languageName: unknown + linkType: soft + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/manifest.json new file mode 100644 index 0000000..133afe1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/manifest.json @@ -0,0 +1,17 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "lodash": "^4.17.21" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..70755f1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/yarn.lock new file mode 100644 index 0000000..5ce111f --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/noop-when-no-protocol-refs/output/workspace/yarn.lock @@ -0,0 +1,23 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + lodash: "npm:^4.17.21" + languageName: unknown + linkType: soft + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + linkType: hard + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + dependencies: + "lodash": "npm:^4.17.21" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/backstage-manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/backstage-manifest.json new file mode 100644 index 0000000..84f5d54 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/backstage-manifest.json @@ -0,0 +1,12 @@ +{ + "backstageVersion": "1.5.0", + "packages": [ + { + "name": "@backstage/config", + "version": "1.5.0", + "dependencies": { + "@backstage/types": "^1.2.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/manifest.json new file mode 100644 index 0000000..8a0e8ec --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/manifest.json @@ -0,0 +1,31 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/shared", + "version": "1.0.0", + "path": "plugins/shared/package.json" + }, + { + "name": "@local/foo", + "version": "1.0.0", + "path": "plugins/foo/package.json", + "dependencies": { + "@local/shared": "workspace:^", + "@backstage/config": "workspace:^" + } + }, + { + "name": "@backstage/config", + "version": "1.5.0", + "path": "packages/config/package.json", + "dependencies": { + "@backstage/types": "^1.2.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/plugins/foo/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/plugins/foo/package.json new file mode 100644 index 0000000..2cce3f1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/plugins/foo/package.json @@ -0,0 +1,9 @@ +{ + "name": "@local/foo", + "version": "1.0.0", + "private": true, + "dependencies": { + "@backstage/config": "workspace:^", + "@local/shared": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/plugins/shared/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/plugins/shared/package.json new file mode 100644 index 0000000..8a66c5e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/plugins/shared/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/shared", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/yarn.lock new file mode 100644 index 0000000..2173676 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/input/workspace/yarn.lock @@ -0,0 +1,23 @@ +__metadata: + version: 8 + +"@local/shared@workspace:plugins/shared": + version: 0.0.0-use.local + resolution: "@local/shared@workspace:plugins/shared" + languageName: unknown + linkType: soft + +"@local/foo@workspace:plugins/foo": + version: 0.0.0-use.local + resolution: "@local/foo@workspace:plugins/foo" + dependencies: + "@local/shared": "workspace:^" + "@backstage/config": "workspace:^" + languageName: unknown + linkType: soft + +"@backstage/config@workspace:^": + version: 1.5.0 + resolution: "@backstage/config@workspace:^" + languageName: node + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/backstage-manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/backstage-manifest.json new file mode 100644 index 0000000..84f5d54 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/backstage-manifest.json @@ -0,0 +1,12 @@ +{ + "backstageVersion": "1.5.0", + "packages": [ + { + "name": "@backstage/config", + "version": "1.5.0", + "dependencies": { + "@backstage/types": "^1.2.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/manifest.json new file mode 100644 index 0000000..8a0e8ec --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/manifest.json @@ -0,0 +1,31 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/shared", + "version": "1.0.0", + "path": "plugins/shared/package.json" + }, + { + "name": "@local/foo", + "version": "1.0.0", + "path": "plugins/foo/package.json", + "dependencies": { + "@local/shared": "workspace:^", + "@backstage/config": "workspace:^" + } + }, + { + "name": "@backstage/config", + "version": "1.5.0", + "path": "packages/config/package.json", + "dependencies": { + "@backstage/types": "^1.2.0" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/plugins/foo/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/plugins/foo/package.json new file mode 100644 index 0000000..24b2ba2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/plugins/foo/package.json @@ -0,0 +1,9 @@ +{ + "name": "@local/foo", + "version": "1.0.0", + "private": true, + "dependencies": { + "@backstage/config": "^1.5.0", + "@local/shared": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/plugins/shared/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/plugins/shared/package.json new file mode 100644 index 0000000..8a66c5e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/plugins/shared/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/shared", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/yarn.lock new file mode 100644 index 0000000..36418eb --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/preserve-local-workspace-ref/output/workspace/yarn.lock @@ -0,0 +1,40 @@ +__metadata: + version: 8 + +"@local/shared@workspace:plugins/shared": + version: 0.0.0-use.local + resolution: "@local/shared@workspace:plugins/shared" + languageName: unknown + linkType: soft + +"@local/foo@workspace:plugins/foo": + version: 0.0.0-use.local + resolution: "@local/foo@workspace:plugins/foo" + dependencies: + "@local/shared": "workspace:^" + "@backstage/config": "npm:^1.5.0" + languageName: unknown + linkType: soft + +"@backstage/config@npm:^1.5.0": + version: 1.5.0 + resolution: "@backstage/config@npm:1.5.0" + dependencies: + "@backstage/types": "npm:^1.2.0" + languageName: node + linkType: hard + +"@local/shared@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/shared@npm:1.0.0" + languageName: node + linkType: hard + +"@local/foo@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/foo@npm:1.0.0" + dependencies: + "@backstage/config": "npm:^1.5.0" + "@local/shared": "npm:^1.0.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/manifest.json new file mode 100644 index 0000000..49a5491 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/manifest.json @@ -0,0 +1,18 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "@gone/missing": "workspace:^", + "lodash": "^4.17.21" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..5e37f48 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/plugins/plugin/package.json @@ -0,0 +1,9 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "@gone/missing": "workspace:^", + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/yarn.lock new file mode 100644 index 0000000..bd1e2fa --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/input/workspace/yarn.lock @@ -0,0 +1,16 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + "@gone/missing": "workspace:^" + lodash: "npm:^4.17.21" + languageName: unknown + linkType: soft + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/manifest.json new file mode 100644 index 0000000..49a5491 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/manifest.json @@ -0,0 +1,18 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "@gone/missing": "workspace:^", + "lodash": "^4.17.21" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..70755f1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/yarn.lock new file mode 100644 index 0000000..8046225 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/removes-stale-unresolvable-dependency/output/workspace/yarn.lock @@ -0,0 +1,24 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + "@gone/missing": "workspace:^" + lodash: "npm:^4.17.21" + languageName: unknown + linkType: soft + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + linkType: hard + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + dependencies: + "lodash": "npm:^4.17.21" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/backstage-manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/backstage-manifest.json new file mode 100644 index 0000000..13ccfbf --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/backstage-manifest.json @@ -0,0 +1,17 @@ +{ + "backstageVersion": "1.42.0", + "packages": [ + { + "name": "@backstage/plugin-catalog-react", + "version": "1.42.0", + "dependencies": { + "@backstage/core-plugin-api": "^1.10.0" + } + }, + { + "name": "@backstage/core-plugin-api", + "version": "1.42.0", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/backstage.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/backstage.json new file mode 100644 index 0000000..de4905a --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/backstage.json @@ -0,0 +1,3 @@ +{ + "version": "1.42.0" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/manifest.json new file mode 100644 index 0000000..a81572d --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/manifest.json @@ -0,0 +1,31 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "@backstage/plugin-catalog-react": "backstage:^" + } + }, + { + "name": "@backstage/plugin-catalog-react", + "version": "1.42.0", + "path": "packages/catalog-react/package.json", + "dependencies": { + "@backstage/core-plugin-api": "backstage:^" + } + }, + { + "name": "@backstage/core-plugin-api", + "version": "1.42.0", + "path": "packages/core-plugin-api/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..3fb8d13 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "@backstage/plugin-catalog-react": "backstage:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/yarn.lock new file mode 100644 index 0000000..09cdd5f --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/input/workspace/yarn.lock @@ -0,0 +1,24 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + "@backstage/plugin-catalog-react": "backstage:^" + languageName: unknown + linkType: soft + +"@backstage/plugin-catalog-react@backstage:^": + version: 1.42.0 + resolution: "@backstage/plugin-catalog-react@backstage:^" + dependencies: + "@backstage/core-plugin-api": "backstage:^" + languageName: node + linkType: soft + +"@backstage/core-plugin-api@backstage:^": + version: 1.42.0 + resolution: "@backstage/core-plugin-api@backstage:^" + languageName: node + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/backstage-manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/backstage-manifest.json new file mode 100644 index 0000000..13ccfbf --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/backstage-manifest.json @@ -0,0 +1,17 @@ +{ + "backstageVersion": "1.42.0", + "packages": [ + { + "name": "@backstage/plugin-catalog-react", + "version": "1.42.0", + "dependencies": { + "@backstage/core-plugin-api": "^1.10.0" + } + }, + { + "name": "@backstage/core-plugin-api", + "version": "1.42.0", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/backstage.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/backstage.json new file mode 100644 index 0000000..de4905a --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/backstage.json @@ -0,0 +1,3 @@ +{ + "version": "1.42.0" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/manifest.json new file mode 100644 index 0000000..a81572d --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/manifest.json @@ -0,0 +1,31 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "@backstage/plugin-catalog-react": "backstage:^" + } + }, + { + "name": "@backstage/plugin-catalog-react", + "version": "1.42.0", + "path": "packages/catalog-react/package.json", + "dependencies": { + "@backstage/core-plugin-api": "backstage:^" + } + }, + { + "name": "@backstage/core-plugin-api", + "version": "1.42.0", + "path": "packages/core-plugin-api/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..4cbeb47 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "@backstage/plugin-catalog-react": "^1.42.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/yarn.lock new file mode 100644 index 0000000..45a10f3 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolve-scrubbed-backstage-dep/output/workspace/yarn.lock @@ -0,0 +1,32 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + "@backstage/plugin-catalog-react": "npm:^1.42.0" + languageName: unknown + linkType: soft + +"@backstage/plugin-catalog-react@npm:^1.42.0": + version: 1.42.0 + resolution: "@backstage/plugin-catalog-react@npm:1.42.0" + dependencies: + "@backstage/core-plugin-api": "npm:^1.10.0" + languageName: node + linkType: hard + +"@backstage/core-plugin-api@npm:^1.10.0, @backstage/core-plugin-api@npm:^1.42.0": + version: 1.42.0 + resolution: "@backstage/core-plugin-api@npm:1.42.0" + languageName: node + linkType: hard + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + dependencies: + "@backstage/plugin-catalog-react": "npm:^1.42.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/manifest.json new file mode 100644 index 0000000..5eb404e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/manifest.json @@ -0,0 +1,23 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "lodash": "^4.17.21" + } + }, + { + "name": "ms", + "version": "2.1.3", + "path": "packages/ms/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..70755f1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/yarn.lock new file mode 100644 index 0000000..3ff737c --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/input/workspace/yarn.lock @@ -0,0 +1,22 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + lodash: "npm:^4.17.21" + languageName: unknown + linkType: soft + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + dependencies: + "ms": "npm:^2.1.3" + linkType: hard + +"ms@npm:^2.1.0": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/manifest.json new file mode 100644 index 0000000..5eb404e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/manifest.json @@ -0,0 +1,23 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "lodash": "^4.17.21" + } + }, + { + "name": "ms", + "version": "2.1.3", + "path": "packages/ms/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..70755f1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/yarn.lock new file mode 100644 index 0000000..205edbb --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-dangling-dep-reference/output/workspace/yarn.lock @@ -0,0 +1,36 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + lodash: "npm:^4.17.21" + languageName: unknown + linkType: soft + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + dependencies: + "ms": "npm:^2.1.3" + linkType: hard + +"ms@npm:^2.1.0": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + linkType: hard + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + dependencies: + "lodash": "npm:^4.17.21" + languageName: node + linkType: hard + +"ms@npm:^2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/manifest.json new file mode 100644 index 0000000..fd672ee --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/manifest.json @@ -0,0 +1,32 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "peerDependencies": { + "@scrubbed/peer-lib": "workspace:^" + }, + "devDependencies": { + "@scrubbed/dev-lib": "workspace:^" + } + }, + { + "name": "@scrubbed/peer-lib", + "version": "2.3.0", + "path": "packages/peer-lib/package.json", + "dependencies": {} + }, + { + "name": "@scrubbed/dev-lib", + "version": "1.1.0", + "path": "packages/dev-lib/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..37773d3 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/plugins/plugin/package.json @@ -0,0 +1,11 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "devDependencies": { + "@scrubbed/dev-lib": "workspace:^" + }, + "peerDependencies": { + "@scrubbed/peer-lib": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/yarn.lock new file mode 100644 index 0000000..4391d82 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/input/workspace/yarn.lock @@ -0,0 +1,24 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + peerDependencies: + "@scrubbed/peer-lib": "workspace:^" + devDependencies: + "@scrubbed/dev-lib": "workspace:^" + languageName: unknown + linkType: soft + +"@scrubbed/peer-lib@workspace:^": + version: 2.3.0 + resolution: "@scrubbed/peer-lib@workspace:^" + languageName: node + linkType: soft + +"@scrubbed/dev-lib@workspace:^": + version: 1.1.0 + resolution: "@scrubbed/dev-lib@workspace:^" + languageName: node + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/manifest.json new file mode 100644 index 0000000..fd672ee --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/manifest.json @@ -0,0 +1,32 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "peerDependencies": { + "@scrubbed/peer-lib": "workspace:^" + }, + "devDependencies": { + "@scrubbed/dev-lib": "workspace:^" + } + }, + { + "name": "@scrubbed/peer-lib", + "version": "2.3.0", + "path": "packages/peer-lib/package.json", + "dependencies": {} + }, + { + "name": "@scrubbed/dev-lib", + "version": "1.1.0", + "path": "packages/dev-lib/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..7508b34 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/plugins/plugin/package.json @@ -0,0 +1,11 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "devDependencies": { + "@scrubbed/dev-lib": "^1.1.0" + }, + "peerDependencies": { + "@scrubbed/peer-lib": "^2.3.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/yarn.lock new file mode 100644 index 0000000..72257b3 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-peer-and-dev-protocol-refs/output/workspace/yarn.lock @@ -0,0 +1,32 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + peerDependencies: + "@scrubbed/peer-lib": "npm:^2.3.0" + devDependencies: + "@scrubbed/dev-lib": "npm:^1.1.0" + languageName: unknown + linkType: soft + +"@scrubbed/peer-lib@npm:^2.3.0": + version: 2.3.0 + resolution: "@scrubbed/peer-lib@npm:2.3.0" + languageName: node + linkType: hard + +"@scrubbed/dev-lib@npm:^1.1.0": + version: 1.1.0 + resolution: "@scrubbed/dev-lib@npm:1.1.0" + languageName: node + linkType: hard + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + peerDependencies: + "@scrubbed/peer-lib": "^2.3.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/overlay/source.json new file mode 100644 index 0000000..189d505 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/overlay/source.json @@ -0,0 +1 @@ +{"repo":"https://github.com/example/repo","repo-ref":"abc123","repo-flat":false,"repo-backstage-version":"1.45.1"} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/manifest.json new file mode 100644 index 0000000..8deb3f4 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/manifest.json @@ -0,0 +1,23 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "@scrubbed/lib": "workspace:^" + } + }, + { + "name": "@scrubbed/lib", + "version": "2.0.0", + "path": "packages/lib/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/package.json new file mode 100644 index 0000000..acacbab --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/package.json @@ -0,0 +1,11 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ], + "resolutions": { + "@scrubbed/lib": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..38b9ea1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "@scrubbed/lib": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/yarn.lock new file mode 100644 index 0000000..c4c2126 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/input/workspace/yarn.lock @@ -0,0 +1,10 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + "@scrubbed/lib": "workspace:^" + languageName: unknown + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/manifest.json new file mode 100644 index 0000000..8deb3f4 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/manifest.json @@ -0,0 +1,23 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "@scrubbed/lib": "workspace:^" + } + }, + { + "name": "@scrubbed/lib", + "version": "2.0.0", + "path": "packages/lib/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/package.json new file mode 100644 index 0000000..3d0a2e8 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/package.json @@ -0,0 +1,11 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ], + "resolutions": { + "@scrubbed/lib": "^2.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..3d467e3 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "@scrubbed/lib": "^2.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/yarn.lock new file mode 100644 index 0000000..63fd9fb --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-protocol-refs-in-resolutions/output/workspace/yarn.lock @@ -0,0 +1,24 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + dependencies: + "@scrubbed/lib": "npm:^2.0.0" + languageName: unknown + linkType: soft + +"@scrubbed/lib@npm:^2.0.0": + version: 2.0.0 + resolution: "@scrubbed/lib@npm:2.0.0" + languageName: node + linkType: hard + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + dependencies: + "@scrubbed/lib": "npm:^2.0.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/manifest.json new file mode 100644 index 0000000..7b3b2e5 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/shared", + "version": "1.0.0", + "path": "plugins/shared/package.json" + }, + { + "name": "@local/consumer", + "version": "1.0.0", + "path": "plugins/consumer/package.json", + "dependencies": { + "@local/shared": "workspace:^", + "@scrubbed/lib": "workspace:^" + } + }, + { + "name": "@scrubbed/lib", + "version": "3.0.0", + "path": "packages/lib/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/plugins/consumer/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/plugins/consumer/package.json new file mode 100644 index 0000000..2fb97f2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/plugins/consumer/package.json @@ -0,0 +1,9 @@ +{ + "name": "@local/consumer", + "version": "1.0.0", + "private": true, + "dependencies": { + "@local/shared": "workspace:^", + "@scrubbed/lib": "workspace:^" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/plugins/shared/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/plugins/shared/package.json new file mode 100644 index 0000000..8a66c5e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/plugins/shared/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/shared", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/yarn.lock new file mode 100644 index 0000000..2ac8ad4 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/input/workspace/yarn.lock @@ -0,0 +1,23 @@ +__metadata: + version: 8 + +"@local/shared@workspace:plugins/shared": + version: 0.0.0-use.local + resolution: "@local/shared@workspace:plugins/shared" + languageName: unknown + linkType: soft + +"@local/consumer@workspace:plugins/consumer": + version: 0.0.0-use.local + resolution: "@local/consumer@workspace:plugins/consumer" + dependencies: + "@local/shared": "workspace:^" + "@scrubbed/lib": "workspace:^" + languageName: unknown + linkType: soft + +"@scrubbed/lib@workspace:^": + version: 3.0.0 + resolution: "@scrubbed/lib@workspace:^" + languageName: node + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/manifest.json new file mode 100644 index 0000000..7b3b2e5 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/shared", + "version": "1.0.0", + "path": "plugins/shared/package.json" + }, + { + "name": "@local/consumer", + "version": "1.0.0", + "path": "plugins/consumer/package.json", + "dependencies": { + "@local/shared": "workspace:^", + "@scrubbed/lib": "workspace:^" + } + }, + { + "name": "@scrubbed/lib", + "version": "3.0.0", + "path": "packages/lib/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/plugins/consumer/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/plugins/consumer/package.json new file mode 100644 index 0000000..9cc4c01 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/plugins/consumer/package.json @@ -0,0 +1,9 @@ +{ + "name": "@local/consumer", + "version": "1.0.0", + "private": true, + "dependencies": { + "@local/shared": "workspace:^", + "@scrubbed/lib": "^3.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/plugins/shared/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/plugins/shared/package.json new file mode 100644 index 0000000..8a66c5e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/plugins/shared/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/shared", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/yarn.lock new file mode 100644 index 0000000..0a8129c --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-scrubbed-workspace-dep-in-lockfile/output/workspace/yarn.lock @@ -0,0 +1,38 @@ +__metadata: + version: 8 + +"@local/shared@workspace:plugins/shared": + version: 0.0.0-use.local + resolution: "@local/shared@workspace:plugins/shared" + languageName: unknown + linkType: soft + +"@local/consumer@workspace:plugins/consumer": + version: 0.0.0-use.local + resolution: "@local/consumer@workspace:plugins/consumer" + dependencies: + "@local/shared": "workspace:^" + "@scrubbed/lib": "npm:^3.0.0" + languageName: unknown + linkType: soft + +"@scrubbed/lib@npm:^3.0.0": + version: 3.0.0 + resolution: "@scrubbed/lib@npm:3.0.0" + languageName: node + linkType: hard + +"@local/shared@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/shared@npm:1.0.0" + languageName: node + linkType: hard + +"@local/consumer@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/consumer@npm:1.0.0" + dependencies: + "@local/shared": "npm:^1.0.0" + "@scrubbed/lib": "npm:^3.0.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/overlay/source.json new file mode 100644 index 0000000..189d505 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/overlay/source.json @@ -0,0 +1 @@ +{"repo":"https://github.com/example/repo","repo-ref":"abc123","repo-flat":false,"repo-backstage-version":"1.45.1"} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/manifest.json new file mode 100644 index 0000000..f67cedc --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/shared", + "version": "1.0.0", + "path": "plugins/shared/package.json" + }, + { + "name": "@local/consumer", + "version": "1.0.0", + "path": "plugins/consumer/package.json", + "dependencies": { + "@local/shared": "workspace:*", + "@scrubbed/lib": "workspace:*" + } + }, + { + "name": "@scrubbed/lib", + "version": "2.0.0", + "path": "packages/lib/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/plugins/consumer/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/plugins/consumer/package.json new file mode 100644 index 0000000..5e9d089 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/plugins/consumer/package.json @@ -0,0 +1,9 @@ +{ + "name": "@local/consumer", + "version": "1.0.0", + "private": true, + "dependencies": { + "@local/shared": "workspace:*", + "@scrubbed/lib": "workspace:*" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/plugins/shared/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/plugins/shared/package.json new file mode 100644 index 0000000..8a66c5e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/plugins/shared/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/shared", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/yarn.lock new file mode 100644 index 0000000..78a0b69 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/input/workspace/yarn.lock @@ -0,0 +1,23 @@ +__metadata: + version: 8 + +"@local/shared@workspace:plugins/shared": + version: 0.0.0-use.local + resolution: "@local/shared@workspace:plugins/shared" + languageName: unknown + linkType: soft + +"@local/consumer@workspace:plugins/consumer": + version: 0.0.0-use.local + resolution: "@local/consumer@workspace:plugins/consumer" + dependencies: + "@local/shared": "workspace:*" + "@scrubbed/lib": "workspace:*" + languageName: unknown + linkType: soft + +"@scrubbed/lib@workspace:*": + version: 2.0.0 + resolution: "@scrubbed/lib@workspace:*" + languageName: node + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/manifest.json new file mode 100644 index 0000000..f67cedc --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/manifest.json @@ -0,0 +1,29 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/shared", + "version": "1.0.0", + "path": "plugins/shared/package.json" + }, + { + "name": "@local/consumer", + "version": "1.0.0", + "path": "plugins/consumer/package.json", + "dependencies": { + "@local/shared": "workspace:*", + "@scrubbed/lib": "workspace:*" + } + }, + { + "name": "@scrubbed/lib", + "version": "2.0.0", + "path": "packages/lib/package.json", + "dependencies": {} + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/plugins/consumer/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/plugins/consumer/package.json new file mode 100644 index 0000000..17e2b98 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/plugins/consumer/package.json @@ -0,0 +1,9 @@ +{ + "name": "@local/consumer", + "version": "1.0.0", + "private": true, + "dependencies": { + "@local/shared": "workspace:*", + "@scrubbed/lib": "^2.0.0" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/plugins/shared/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/plugins/shared/package.json new file mode 100644 index 0000000..8a66c5e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/plugins/shared/package.json @@ -0,0 +1,5 @@ +{ + "name": "@local/shared", + "version": "1.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/yarn.lock new file mode 100644 index 0000000..2ecdd20 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/resolves-workspace-star-protocol/output/workspace/yarn.lock @@ -0,0 +1,38 @@ +__metadata: + version: 8 + +"@local/shared@workspace:plugins/shared": + version: 0.0.0-use.local + resolution: "@local/shared@workspace:plugins/shared" + languageName: unknown + linkType: soft + +"@local/consumer@workspace:plugins/consumer": + version: 0.0.0-use.local + resolution: "@local/consumer@workspace:plugins/consumer" + dependencies: + "@local/shared": "workspace:*" + "@scrubbed/lib": "npm:^2.0.0" + languageName: unknown + linkType: soft + +"@scrubbed/lib@npm:^2.0.0": + version: 2.0.0 + resolution: "@scrubbed/lib@npm:2.0.0" + languageName: node + linkType: hard + +"@local/shared@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/shared@npm:1.0.0" + languageName: node + linkType: hard + +"@local/consumer@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/consumer@npm:1.0.0" + dependencies: + "@local/shared": "npm:1.0.0" + "@scrubbed/lib": "npm:2.0.0" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/manifest.json new file mode 100644 index 0000000..133afe1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/manifest.json @@ -0,0 +1,17 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "lodash": "^4.17.21" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..70755f1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/yarn.lock new file mode 100644 index 0000000..5bb58b7 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/input/workspace/yarn.lock @@ -0,0 +1,8 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + languageName: unknown + linkType: soft diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/manifest.json new file mode 100644 index 0000000..133afe1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/manifest.json @@ -0,0 +1,17 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + }, + { + "name": "@local/plugin", + "version": "1.0.0", + "path": "plugins/plugin/package.json", + "dependencies": { + "lodash": "^4.17.21" + } + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/package.json new file mode 100644 index 0000000..faa7df2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/package.json @@ -0,0 +1,8 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true, + "workspaces": [ + "plugins/*" + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/plugins/plugin/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/plugins/plugin/package.json new file mode 100644 index 0000000..70755f1 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/plugins/plugin/package.json @@ -0,0 +1,8 @@ +{ + "name": "@local/plugin", + "version": "1.0.0", + "private": true, + "dependencies": { + "lodash": "^4.17.21" + } +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/yarn.lock b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/yarn.lock new file mode 100644 index 0000000..f794e98 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/skips-type-shims-when-not-needed/output/workspace/yarn.lock @@ -0,0 +1,16 @@ +__metadata: + version: 8 + +"@local/plugin@workspace:plugins/plugin": + version: 0.0.0-use.local + resolution: "@local/plugin@workspace:plugins/plugin" + languageName: unknown + linkType: soft + +"@local/plugin@npm:^1.0.0": + version: 1.0.0 + resolution: "@local/plugin@npm:1.0.0" + dependencies: + "lodash": "npm:^4.17.21" + languageName: node + linkType: hard diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/error b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/error new file mode 100644 index 0000000..d06e246 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/error @@ -0,0 +1 @@ +manifest.json not found — run generate-manifests first diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/input/workspace/package.json new file mode 100644 index 0000000..8e2a32d --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-manifest-missing/input/workspace/package.json @@ -0,0 +1,5 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/error b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/error new file mode 100644 index 0000000..469189f --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/error @@ -0,0 +1 @@ +yarn.lock not found at workspace root diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/overlay/source.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/overlay/source.json new file mode 100644 index 0000000..2d01d75 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/overlay/source.json @@ -0,0 +1,6 @@ +{ + "repo": "https://github.com/example/repo", + "repo-ref": "abc123", + "repo-flat": false, + "repo-backstage-version": "1.45.1" +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/workspace/manifest.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/workspace/manifest.json new file mode 100644 index 0000000..dbbeb37 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/workspace/manifest.json @@ -0,0 +1,9 @@ +{ + "packages": [ + { + "name": "test-workspace", + "version": "0.0.0", + "path": "package.json" + } + ] +} diff --git a/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/workspace/package.json b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/workspace/package.json new file mode 100644 index 0000000..8e2a32d --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/__fixtures__/throws-when-yarn-lock-missing/input/workspace/package.json @@ -0,0 +1,5 @@ +{ + "name": "test-workspace", + "version": "0.0.0", + "private": true +} diff --git a/prepare-sources/lib/modules/protocol-resolution/constants.ts b/prepare-sources/lib/modules/protocol-resolution/constants.ts new file mode 100644 index 0000000..26762bc --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/constants.ts @@ -0,0 +1,28 @@ +/** Protocols used for workspace-internal references (excluded from type-shims stubs). */ +export const INTERNAL_PROTOCOLS = ["workspace:", "backstage:"] as const; + +/** Host dependencies required by frontend plugins (provided by app packages). */ +export const HOST_DEPS = ["react", "react-dom", "react-router", "react-router-dom"] as const; + +export const TYPE_SHIMS_NAME = "@internal/type-shims"; +export const TYPE_SHIMS_DIR = "packages/type-shims"; + +export const IGNORE_DIRS = new Set([ + "node_modules", + ".git", + "dist", + "dist-dynamic", + "build", + "coverage", +]); + +export const DEP_SECTIONS = [ + "resolutions", + "dependencies", + "devDependencies", + "peerDependencies", + "optionalDependencies", +] as const; + +/** Runtime packages whose @types/* are referenced via global-augments.d.ts. */ +export const EXTRA_RUNTIME_TYPES = new Set(["compression"]); diff --git a/prepare-sources/lib/modules/protocol-resolution/index.test.ts b/prepare-sources/lib/modules/protocol-resolution/index.test.ts new file mode 100644 index 0000000..90f8e6c --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/index.test.ts @@ -0,0 +1,91 @@ +import fs from "node:fs"; +import path from "node:path"; +import { afterEach, describe, expect, it, vi } from "vite-plus/test"; + +import { mockFetch, testInputOutputExpectations } from "../../test-utils.ts"; +import { clearNpmMetadataCache } from "./npm-metadata.ts"; +import { caretOrTildeSatisfies } from "./semver-range.ts"; +import { buildVersionMap } from "./version-map.ts"; +import { run } from "./index.ts"; + +afterEach(() => { + vi.restoreAllMocks(); + clearNpmMetadataCache(); +}); + +/** + * Fixture catalog (`__fixtures__//` — name doubles as the Vitest case title): + * + * - `preserve-local-workspace-ref` — `workspace:^` kept for surviving local packages; + * scrubbed `@backstage/config` resolved to `^1.5.0` in package.json and yarn.lock + * - `resolve-scrubbed-backstage-dep` — `backstage:^` → npm semver ranges; dangling + * resolution blocks created for scrubbed Backstage packages + * - `resolves-dangling-dep-reference` — dep body references a specifier with no block; + * a new hard npm block is created to satisfy it. + * - `enriches-npm-block-specifiers` — npm block keys gain missing specifiers referenced + * by other blocks' dependency maps (e.g. `ms@npm:^2.1.3` added alongside `^2.1.0`) + * - `resolves-peer-and-dev-protocol-refs` — `workspace:^` in peerDependencies and + * devDependencies resolved to npm ranges + * - `creates-combined-key-for-local-with-npm-refs` — surviving local package gets a + * separate hard npm resolution block; soft workspace block keeps workspace-only key + * - `creates-hard-npm-blocks-for-local-packages` — comprehensive local+scrubbed scenario: + * soft workspace blocks preserved, hard npm blocks created for all local and scrubbed + * packages, dangling deps (e.g. @backstage/types) resolved transitively + * - `resolves-scrubbed-workspace-dep-in-lockfile` — scrubbed `workspace:^` block + * replaced with npm resolution block; surviving local `workspace:^` preserved + * - `creates-type-shims-from-scrubbed-app` — scrubbed `packages/app` in manifest (dir + * absent) triggers `@internal/type-shims` for frontend plugin imports + * - `deletes-stale-workspace-path-lockfile-blocks` — `workspace:packages/app` blocks + * removed when the path no longer exists on disk + * - `removes-stale-unresolvable-dependency` — `@gone/missing: workspace:^` dropped from + * package.json when not in version map and not on disk; yarn.lock dep-map entry + * intentionally kept (lockfile dep cleanup is handled by a later pipeline stage) + * - `noop-when-no-protocol-refs` — workspace with only npm deps; no output/ changes + * - `skips-type-shims-when-not-needed` — protocol resolution without scrubbed app/types + * need; no type-shims package created + * - `throws-when-manifest-missing` — error when `manifest.json` absent + * - `throws-when-yarn-lock-missing` — error when `yarn.lock` absent + */ +describe("protocol-resolution", () => { + testInputOutputExpectations(import.meta.dirname, run, { + setup: (fixture, fixtureDir) => { + const npmResponsesDir = path.join(fixtureDir, "npm-responses"); + if (!fs.existsSync(npmResponsesDir)) return; + + const mappings: Record = {}; + for (const file of fs.readdirSync(npmResponsesDir)) { + if (!file.endsWith(".json")) continue; + const [pkg = "", version = ""] = file.replace(".json", "").split("@"); + const scoped = pkg.includes("__") ? pkg.replace("__", "/") : pkg; + const packageName = scoped.startsWith("@") ? scoped : scoped; + const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/${version}`; + mappings[url] = JSON.parse(fs.readFileSync(path.join(npmResponsesDir, file), "utf8")); + } + if (Object.keys(mappings).length > 0) mockFetch(mappings); + }, + }); + + it("buildVersionMap merges workspace and backstage manifests", () => { + const map = buildVersionMap( + { + packages: [ + { name: "@local/pkg", version: "1.0.0" }, + { name: "@shared/pkg", version: "2.0.0" }, + ], + }, + { + backstageVersion: "1.42.0", + packages: [{ name: "@backstage/core", version: "1.42.0" }], + }, + ); + expect(map.get("@local/pkg")).toBe("1.0.0"); + expect(map.get("@backstage/core")).toBe("1.42.0"); + }); + + it("caretOrTildeSatisfies handles caret ranges", () => { + expect(caretOrTildeSatisfies("1.2.5", "^", "1.2.0")).toBe(true); + expect(caretOrTildeSatisfies("1.3.0", "^", "1.2.0")).toBe(true); + expect(caretOrTildeSatisfies("2.0.0", "^", "1.2.0")).toBe(false); + expect(caretOrTildeSatisfies("1.2", "^", "1.2.0")).toBe(false); + }); +}); diff --git a/prepare-sources/lib/modules/protocol-resolution/index.ts b/prepare-sources/lib/modules/protocol-resolution/index.ts new file mode 100644 index 0000000..5fcdcb2 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/index.ts @@ -0,0 +1,59 @@ +import fs from "node:fs"; +import path from "node:path"; +import type { ModuleContext } from "../../pipeline.ts"; +import { updatePackageJsonProtocols } from "./package-json.ts"; +import { createTypeShimsPackage } from "./type-shims.ts"; +import { findPackageJsonFiles } from "./utils.ts"; +import { buildVersionMap, loadBackstageManifest, loadWorkspaceManifest } from "./version-map.ts"; +import { updateYarnLock } from "./yarn-lock-update.ts"; + +/** + * Resolves `workspace:^` and `backstage:^` protocol references to concrete npm + * semver ranges in `package.json` and `yarn.lock`, and creates `packages/type-shims` + * when surviving code needs types from scrubbed packages. + * + * Equivalent to `update-workspace.js --update` plus the type-shims portion of `--delete`. + * Lockfile entry deletion for scrubbed packages is handled by `package-cleanup`. + */ +export async function run(ctx: ModuleContext): Promise { + const workspaceManifest = loadWorkspaceManifest(ctx.workspacePath); + const backstageManifest = loadBackstageManifest(ctx.workspacePath); + const versionMap = buildVersionMap(workspaceManifest, backstageManifest); + + ctx.log(`version map: ${versionMap.size} entries`); + + const yarnLockPath = path.join(ctx.workspacePath, "yarn.lock"); + if (!fs.existsSync(yarnLockPath)) { + throw new Error("yarn.lock not found at workspace root"); + } + + const packageJsonFiles = findPackageJsonFiles(ctx.workspacePath); + ctx.log(`processing ${packageJsonFiles.length} package.json file(s)`); + + let totalReplacements = 0; + let yarnLockProcessed = false; + + for (const pkgPath of packageJsonFiles) { + const result = updatePackageJsonProtocols(pkgPath, ctx.workspacePath, versionMap, ctx.log); + totalReplacements += result.replacements; + + if (!yarnLockProcessed) { + await updateYarnLock( + yarnLockPath, + versionMap, + workspaceManifest, + backstageManifest, + ctx.workspacePath, + ctx.log, + ); + yarnLockProcessed = true; + } + } + + ctx.log( + `package.json: ${totalReplacements} replacement(s); yarn.lock ${yarnLockProcessed ? "updated" : "skipped"}`, + ); + + ctx.log("creating type-shims package if needed..."); + createTypeShimsPackage(ctx.workspacePath, workspaceManifest, ctx.log); +} diff --git a/prepare-sources/lib/modules/protocol-resolution/npm-metadata.ts b/prepare-sources/lib/modules/protocol-resolution/npm-metadata.ts new file mode 100644 index 0000000..c487855 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/npm-metadata.ts @@ -0,0 +1,84 @@ +export type NpmPackageMetadata = { + dependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; + peerDependenciesMeta?: Record>; + bin?: Record | string; +}; + +const npmMetadataCache = new Map(); +const MAX_RETRIES = 3; +const INITIAL_DELAY_MS = 1000; + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +/** + * Fetch package metadata from the npm registry for an exact version. + * Retries transient failures; negative-caches permanent 404s. + */ +export async function fetchNpmPackageMetadata( + packageName: string, + version: string, + log: (message: string) => void, +): Promise { + const cacheKey = `${packageName}@${version}`; + if (npmMetadataCache.has(cacheKey)) { + return npmMetadataCache.get(cacheKey) ?? null; + } + + const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/${version}`; + + for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) { + try { + const response = await fetch(url); + if (response.status >= 400) { + const isTransient = response.status === 429 || response.status >= 500; + if (isTransient && attempt < MAX_RETRIES) { + const delayMs = INITIAL_DELAY_MS * 2 ** (attempt - 1); + log( + `npm fetch attempt ${attempt}/${MAX_RETRIES} got HTTP ${response.status} for ${packageName}@${version}, retrying in ${delayMs}ms`, + ); + await sleep(delayMs); + continue; + } + if (!isTransient) { + log(`npm registry returned HTTP ${response.status} for ${packageName}@${version}`); + npmMetadataCache.set(cacheKey, null); + } + return null; + } + + const parsed = await response.json(); + if (typeof parsed !== "object" || parsed === null || parsed.error) { + log(`npm registry returned error for ${packageName}@${version}`); + npmMetadataCache.set(cacheKey, null); + return null; + } + + npmMetadataCache.set(cacheKey, parsed); + return parsed; + } catch (error) { + if (attempt < MAX_RETRIES) { + const delayMs = INITIAL_DELAY_MS * 2 ** (attempt - 1); + log( + `npm fetch attempt ${attempt}/${MAX_RETRIES} failed for ${packageName}@${version}: ${String(error)}`, + ); + await sleep(delayMs); + continue; + } + log( + `could not fetch npm metadata for ${packageName}@${version} after ${MAX_RETRIES} attempts`, + ); + return null; + } + } + + return null; +} + +/** Clear the in-memory npm metadata cache (for tests). */ +export function clearNpmMetadataCache(): void { + npmMetadataCache.clear(); +} diff --git a/prepare-sources/lib/modules/protocol-resolution/package-json.ts b/prepare-sources/lib/modules/protocol-resolution/package-json.ts new file mode 100644 index 0000000..a8af0ab --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/package-json.ts @@ -0,0 +1,75 @@ +import fs from "node:fs"; +import path from "node:path"; +import { DEP_SECTIONS } from "./constants.ts"; +import { findPackageVersion, writeJson } from "./utils.ts"; + +export type PackageJsonUpdateResult = { + replacements: number; + changed: boolean; +}; + +function isProtocolRef(version: string): boolean { + return version.startsWith("workspace:") || version === "backstage:^"; +} + +/** + * Replace workspace:^ and backstage:^ references in a single package.json. + * Preserves workspace:^ for packages that still exist locally on disk. + */ +export function updatePackageJsonProtocols( + packageJsonPath: string, + workspacePath: string, + versionMap: Map, + log: (message: string) => void, +): PackageJsonUpdateResult { + const content = fs.readFileSync(packageJsonPath, "utf8"); + const updated = JSON.parse(content); + let replacements = 0; + + for (const section of DEP_SECTIONS) { + const deps = updated[section]; + if (!deps || typeof deps !== "object") continue; + + const toDelete: string[] = []; + + for (const [packageName, version] of Object.entries(deps)) { + if (typeof version !== "string" || !isProtocolRef(version)) continue; + + if (version.startsWith("workspace:")) { + if (findPackageVersion(packageName, workspacePath) !== null) continue; + } + + const isBackstageDep = version === "backstage:^"; + let newVersion = + versionMap.get(packageName) ?? + (isBackstageDep ? versionMap.get(packageName) : undefined) ?? + findPackageVersion(packageName, workspacePath); + + if (newVersion) { + log( + `${path.relative(workspacePath, packageJsonPath)} ${section}: ${packageName}: ${version} → ^${newVersion}`, + ); + deps[packageName] = `^${newVersion}`; + replacements++; + } else if (findPackageVersion(packageName, workspacePath) === null) { + log( + `${path.relative(workspacePath, packageJsonPath)} ${section}: removing stale dependency ${packageName}`, + ); + toDelete.push(packageName); + replacements++; + } else { + log(`warning: no version found for ${packageName} in manifests`); + } + } + + for (const name of toDelete) { + delete deps[name]; + } + } + + if (replacements > 0) { + writeJson(packageJsonPath, updated); + } + + return { replacements, changed: replacements > 0 }; +} diff --git a/prepare-sources/lib/modules/protocol-resolution/semver-range.ts b/prepare-sources/lib/modules/protocol-resolution/semver-range.ts new file mode 100644 index 0000000..85d5e51 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/semver-range.ts @@ -0,0 +1,42 @@ +/** + * Check whether a resolved version satisfies a caret (^) or tilde (~) range. + * Handles common semver cases without an external library. + */ +export function caretOrTildeSatisfies( + resolved: string, + prefix: "^" | "~", + rangeVersion: string, +): boolean { + const rParts = resolved.split(".").map(Number); + const sParts = rangeVersion.split(".").map(Number); + + const rMaj = rParts[0]; + const rMin = rParts[1]; + const rPatch = rParts[2]; + const sMaj = sParts[0]; + const sMin = sParts[1]; + const sPatch = sParts[2]; + if ( + rMaj === undefined || + rMin === undefined || + rPatch === undefined || + sMaj === undefined || + sMin === undefined || + sPatch === undefined + ) { + return false; + } + + if (prefix === "~") { + return rMaj === sMaj && rMin === sMin && rPatch >= sPatch; + } + + if (rMaj !== sMaj) return false; + if (sMaj > 0) { + return rMin > sMin || (rMin === sMin && rPatch >= sPatch); + } + if (sMin > 0) { + return rMin === sMin && rPatch >= sPatch; + } + return rPatch === sPatch; +} diff --git a/prepare-sources/lib/modules/protocol-resolution/type-shims.ts b/prepare-sources/lib/modules/protocol-resolution/type-shims.ts new file mode 100644 index 0000000..62dddd8 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/type-shims.ts @@ -0,0 +1,370 @@ +import fs from "node:fs"; +import path from "node:path"; +import type { WorkspaceManifest } from "../../manifest-types.ts"; +import { + EXTRA_RUNTIME_TYPES, + HOST_DEPS, + INTERNAL_PROTOCOLS, + TYPE_SHIMS_DIR, + TYPE_SHIMS_NAME, +} from "./constants.ts"; +import { parseLockfile, serializeLockfile } from "../../yarn-lock-parser.ts"; +import { buildWorkspaceSoftBlock } from "./yarn-lock-metadata.ts"; +import { writeJson } from "./utils.ts"; + +function typesPackageToRuntime(name: string): string | null { + if (!name.startsWith("@types/")) return null; + const raw = name.slice("@types/".length); + if (raw.includes("__")) { + const [scope, ...rest] = raw.split("__"); + return `@${scope}/${rest.join("__")}`; + } + return raw; +} + +function collectTsconfigTypes(workspacePath: string): Set { + const types = new Set(); + const tsconfigPath = path.join(workspacePath, "tsconfig.json"); + if (!fs.existsSync(tsconfigPath)) return types; + try { + const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, "utf8")); + if (tsconfig.compilerOptions?.types) { + for (const t of tsconfig.compilerOptions.types) types.add(t); + } + } catch { + // ignore parse errors + } + return types; +} + +function collectImportsFromSurvivingFiles(dirs: string[]): Set { + const imports = new Set(); + const importRegex = /(?<=(?:from|import)\s+['"])(@[^'"/]+\/[^'"/]+|[^'"./][^'"/]*)/gm; + const requireRegex = /(?<=require\s*\(\s*['"])(@[^'"/]+\/[^'"/]+|[^'"./][^'"/]*)(?=['"]\s*\))/gm; + + for (const dir of dirs) { + const files: string[] = []; + + function walk(d: string): void { + if (!fs.existsSync(d)) return; + let entries: fs.Dirent[]; + try { + entries = fs.readdirSync(d, { withFileTypes: true }); + } catch { + return; + } + for (const entry of entries) { + if ( + ["node_modules", "dist", "dist-dynamic", ".git", "build", "coverage"].includes(entry.name) + ) { + continue; + } + const full = path.join(d, entry.name); + if (entry.isDirectory()) walk(full); + else if (/\.(tsx?|jsx?)$/.test(entry.name)) files.push(full); + } + } + walk(dir); + + for (const file of files) { + let content: string; + try { + content = fs.readFileSync(file, "utf8"); + } catch { + continue; + } + for (const regex of [importRegex, requireRegex]) { + regex.lastIndex = 0; + let match: RegExpExecArray | null; + while ((match = regex.exec(content)) !== null) { + imports.add(match[0]); + } + } + } + } + return imports; +} + +function survivingCodeUsesAssetTypes(dirs: string[]): boolean { + const assetRe = + /(?:from|import)\s+['"]\..*\.(module\.css|css|scss|sass|svg|png|jpg|jpeg|gif|bmp|ico|woff|woff2|ttf|eot|yaml|md)['"]/; + + for (const dir of dirs) { + function walk(d: string): boolean { + if (!fs.existsSync(d)) return false; + let entries: fs.Dirent[]; + try { + entries = fs.readdirSync(d, { withFileTypes: true }); + } catch { + return false; + } + for (const entry of entries) { + if ( + ["node_modules", "dist", "dist-dynamic", ".git", "build", "coverage"].includes(entry.name) + ) { + continue; + } + const full = path.join(d, entry.name); + if (entry.isDirectory()) { + if (walk(full)) return true; + } else if (/\.(tsx?|jsx?)$/.test(entry.name)) { + let content: string; + try { + content = fs.readFileSync(full, "utf8"); + } catch { + continue; + } + if (assetRe.test(content)) return true; + } + } + return false; + } + if (walk(dir)) return true; + } + return false; +} + +function tsconfigHasAssetTypes(workspacePath: string): boolean { + const tsconfigPath = path.join(workspacePath, "tsconfig.json"); + if (!fs.existsSync(tsconfigPath)) return false; + try { + const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, "utf8")); + return (tsconfig.files ?? []).some((f: string) => f.includes("asset-types")); + } catch { + return false; + } +} + +function addTypeShimsToRootPackageJson( + workspacePath: string, + log: (message: string) => void, +): void { + const rootPkgPath = path.join(workspacePath, "package.json"); + const rootPkg = JSON.parse(fs.readFileSync(rootPkgPath, "utf8")); + + if (!rootPkg.workspaces) { + rootPkg.workspaces = { packages: [] }; + } + + const pkgsList = Array.isArray(rootPkg.workspaces) + ? rootPkg.workspaces + : (rootPkg.workspaces.packages ?? []); + + if (!pkgsList.includes(TYPE_SHIMS_DIR)) { + pkgsList.push(TYPE_SHIMS_DIR); + if (Array.isArray(rootPkg.workspaces)) { + rootPkg.workspaces = pkgsList; + } else { + rootPkg.workspaces.packages = pkgsList; + } + writeJson(rootPkgPath, rootPkg); + log(`added ${TYPE_SHIMS_DIR} to root package.json workspaces`); + } +} + +function addTypeShimsToTsconfigReferences( + workspacePath: string, + log: (message: string) => void, +): void { + const tsconfigPath = path.join(workspacePath, "tsconfig.json"); + if (!fs.existsSync(tsconfigPath)) return; + + try { + const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, "utf8")); + if (!tsconfig.references) tsconfig.references = []; + + if (!tsconfig.references.some((r: { path: string }) => r.path === TYPE_SHIMS_DIR)) { + tsconfig.references.push({ path: TYPE_SHIMS_DIR }); + writeJson(tsconfigPath, tsconfig); + log(`added ${TYPE_SHIMS_DIR} to root tsconfig.json references`); + } + } catch (error) { + log(`warning: could not update tsconfig.json references: ${String(error)}`); + } +} + +function preWireTypeShimsInYarnLock( + workspacePath: string, + deps: Record, + devDeps: Record, + log: (message: string) => void, +): void { + const yarnLockPath = path.join(workspacePath, "yarn.lock"); + if (!fs.existsSync(yarnLockPath)) { + log("warning: yarn.lock not found, skipping type-shims pre-wiring"); + return; + } + + const lockfile = parseLockfile(fs.readFileSync(yarnLockPath, "utf8")); + const descriptor = `${TYPE_SHIMS_NAME}@workspace:${TYPE_SHIMS_DIR}`; + + if (lockfile.blocks.some((b) => b.descriptors.includes(descriptor))) { + log("type-shims yarn.lock entry already exists, skipping pre-wire"); + return; + } + + lockfile.blocks.push(buildWorkspaceSoftBlock(TYPE_SHIMS_NAME, TYPE_SHIMS_DIR, deps, devDeps)); + fs.writeFileSync(yarnLockPath, serializeLockfile(lockfile)); + log(`pre-wired ${TYPE_SHIMS_NAME} entry in yarn.lock`); +} + +/** + * Create `packages/type-shims` aggregating host deps and @types/* from scrubbed packages. + */ +export function createTypeShimsPackage( + workspacePath: string, + manifest: WorkspaceManifest, + log: (message: string) => void, +): void { + const survivingPeerDeps = new Set(); + const survivingDeps = new Set(); + const survivingDirs: string[] = []; + + for (const pkg of manifest.packages) { + if (!pkg.path || pkg.path === "upstream") continue; + const pkgDir = path.dirname(path.join(workspacePath, pkg.path)); + if (!fs.existsSync(pkgDir)) continue; + survivingDirs.push(pkgDir); + if (pkg.peerDependencies) { + Object.keys(pkg.peerDependencies).forEach((n) => survivingPeerDeps.add(n)); + } + if (pkg.dependencies) { + Object.keys(pkg.dependencies).forEach((n) => survivingDeps.add(n)); + } + } + + const alreadyProvided = new Set(); + for (const pkg of manifest.packages) { + if (!pkg.path || pkg.path === "upstream") continue; + const pkgDir = path.dirname(path.join(workspacePath, pkg.path)); + if (!fs.existsSync(pkgDir)) continue; + for (const section of ["dependencies", "devDependencies", "peerDependencies"] as const) { + if (pkg[section]) Object.keys(pkg[section]).forEach((n) => alreadyProvided.add(n)); + } + } + + const rootPkgPath = path.join(workspacePath, "package.json"); + const rootPkg = JSON.parse(fs.readFileSync(rootPkgPath, "utf8")); + const rootDevDeps = new Set(Object.keys(rootPkg.devDependencies ?? {})); + for (const section of ["dependencies", "devDependencies"] as const) { + if (rootPkg[section]) Object.keys(rootPkg[section]).forEach((n) => alreadyProvided.add(n)); + } + + const tsconfigTypes = collectTsconfigTypes(workspacePath); + log("scanning surviving source files for imports..."); + const survivingImports = collectImportsFromSurvivingFiles(survivingDirs); + log(`found ${survivingImports.size} unique import targets`); + + const needsAssetTypes = + !tsconfigHasAssetTypes(workspacePath) && + !survivingImports.has("@backstage/cli/asset-types") && + survivingCodeUsesAssetTypes(survivingDirs); + + const needsThemeAugmentation = + survivingImports.has("@mui/styles") && + !survivingImports.has("@backstage/core-components") && + !survivingImports.has("@backstage/theme"); + + function isNeededDevDep(name: string, version: string): boolean { + if (INTERNAL_PROTOCOLS.some((p) => version.startsWith(p))) return false; + if (alreadyProvided.has(name)) return false; + if (survivingImports.has(name)) return true; + + if (name.startsWith("@types/")) { + const runtimePkg = typesPackageToRuntime(name); + if (runtimePkg) { + if (survivingImports.has(runtimePkg)) return true; + if (survivingPeerDeps.has(runtimePkg)) return true; + if (survivingDeps.has(runtimePkg)) return true; + if (rootDevDeps.has(runtimePkg)) return true; + if (tsconfigTypes.has(runtimePkg)) return true; + if (EXTRA_RUNTIME_TYPES.has(runtimePkg)) return true; + } + } + return false; + } + + const aggregatedDeps: Record = {}; + const aggregatedDevDeps: Record = {}; + + for (const pkg of manifest.packages) { + if (!pkg.path || pkg.path === "upstream") continue; + const pkgDir = path.dirname(path.join(workspacePath, pkg.path)); + if (fs.existsSync(pkgDir)) continue; + + const folderName = path.basename(pkgDir); + + if (["app", "app-next"].includes(folderName) && pkg.dependencies) { + for (const dep of HOST_DEPS) { + if (pkg.dependencies[dep] && !aggregatedDeps[dep]) { + aggregatedDeps[dep] = pkg.dependencies[dep]; + } + } + } + + if (pkg.devDependencies) { + for (const [name, version] of Object.entries(pkg.devDependencies)) { + if (!aggregatedDevDeps[name] && isNeededDevDep(name, version)) { + aggregatedDevDeps[name] = version; + } + } + } + } + + if ( + Object.keys(aggregatedDeps).length === 0 && + Object.keys(aggregatedDevDeps).length === 0 && + !needsAssetTypes && + !needsThemeAugmentation + ) { + log("no type-shims package needed"); + return; + } + + const shimDir = path.join(workspacePath, TYPE_SHIMS_DIR); + fs.mkdirSync(shimDir, { recursive: true }); + + const pkgJson: Record = { + name: TYPE_SHIMS_NAME, + version: "0.0.0-use.local", + private: true, + }; + if (Object.keys(aggregatedDeps).length > 0) pkgJson.dependencies = aggregatedDeps; + if (Object.keys(aggregatedDevDeps).length > 0) pkgJson.devDependencies = aggregatedDevDeps; + writeJson(path.join(shimDir, "package.json"), pkgJson); + + let shim = ""; + if (needsAssetTypes) shim += "import '@backstage/cli/asset-types';\n"; + if (needsThemeAugmentation) shim += "import '@backstage/theme';\n"; + + const extraTypeRefs = Object.keys(aggregatedDevDeps) + .filter((n) => n.startsWith("@types/")) + .map((n) => typesPackageToRuntime(n)) + .filter((rt): rt is string => rt !== null && EXTRA_RUNTIME_TYPES.has(rt)); + + for (const rt of extraTypeRefs) { + shim += `import '${rt}';\n`; + } + + if (shim) { + const srcDir = path.join(shimDir, "src"); + fs.mkdirSync(srcDir, { recursive: true }); + fs.writeFileSync(path.join(srcDir, "global-augments.d.ts"), shim); + log(`created ${path.relative(workspacePath, srcDir)}/global-augments.d.ts`); + } + + writeJson(path.join(shimDir, "tsconfig.json"), { + extends: "../../tsconfig.json", + compilerOptions: { composite: true }, + include: ["src"], + }); + + log( + `created ${TYPE_SHIMS_DIR} (${TYPE_SHIMS_NAME}): ` + + `${Object.keys(aggregatedDeps).length} deps, ${Object.keys(aggregatedDevDeps).length} devDeps`, + ); + + addTypeShimsToRootPackageJson(workspacePath, log); + addTypeShimsToTsconfigReferences(workspacePath, log); + preWireTypeShimsInYarnLock(workspacePath, aggregatedDeps, aggregatedDevDeps, log); +} diff --git a/prepare-sources/lib/modules/protocol-resolution/utils.ts b/prepare-sources/lib/modules/protocol-resolution/utils.ts new file mode 100644 index 0000000..c1efb53 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/utils.ts @@ -0,0 +1,89 @@ +import fs from "node:fs"; +import path from "node:path"; +import { IGNORE_DIRS } from "./constants.ts"; + +export function writeJson(filePath: string, data: unknown): void { + fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n"); +} + +/** Discover all package.json files under the workspace (excluding build output dirs). */ +export function findPackageJsonFiles(workspacePath: string): string[] { + const results: string[] = []; + + function search(currentDir: string): void { + let entries: fs.Dirent[]; + try { + entries = fs.readdirSync(currentDir, { withFileTypes: true }); + } catch { + return; + } + + for (const entry of entries) { + const fullPath = path.join(currentDir, entry.name); + if (entry.isDirectory()) { + if (!IGNORE_DIRS.has(entry.name)) search(fullPath); + } else if (entry.isFile() && entry.name === "package.json") { + results.push(fullPath); + } + } + } + + search(path.resolve(workspacePath)); + return results; +} + +/** + * Find a package version by scanning workspace package.json files. + * Limits recursion depth to avoid runaway traversal. + */ +export function findPackageVersion( + packageName: string, + workspacePath: string, + maxDepth = 5, +): string | null { + const searchDirs = [workspacePath, path.join(workspacePath, "plugins")]; + + function searchRecursive(dir: string, depth: number): string | null { + if (depth > maxDepth || !fs.existsSync(dir)) return null; + + let entries: fs.Dirent[]; + try { + entries = fs.readdirSync(dir, { withFileTypes: true }); + } catch { + return null; + } + + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + if ( + entry.isDirectory() && + !entry.name.startsWith(".") && + entry.name !== "node_modules" && + entry.name !== "dist-dynamic" + ) { + const found = searchRecursive(fullPath, depth + 1); + if (found) return found; + } else if (entry.isFile() && entry.name === "package.json") { + try { + const pkg = JSON.parse(fs.readFileSync(fullPath, "utf8")); + if (pkg.name === packageName && pkg.version) return pkg.version; + } catch { + // skip invalid JSON + } + } + } + return null; + } + + for (const searchDir of searchDirs) { + const version = searchRecursive(searchDir, 0); + if (version) return version; + } + return null; +} + +/** Extract package name from a yarn.lock block key specifier segment. */ +export function extractPackageNameFromSpecifier(specifier: string): string | null { + const match = specifier.match(/^(?:@[^@/]+\/)?[^@"]+/); + return match ? match[0] : null; +} diff --git a/prepare-sources/lib/modules/protocol-resolution/version-map.ts b/prepare-sources/lib/modules/protocol-resolution/version-map.ts new file mode 100644 index 0000000..5806ba0 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/version-map.ts @@ -0,0 +1,39 @@ +import fs from "node:fs"; +import path from "node:path"; +import type { BackstageManifest, WorkspaceManifest } from "../../manifest-types.ts"; + +export function loadWorkspaceManifest(workspacePath: string): WorkspaceManifest { + const manifestPath = path.join(workspacePath, "manifest.json"); + if (!fs.existsSync(manifestPath)) { + throw new Error("manifest.json not found — run generate-manifests first"); + } + return JSON.parse(fs.readFileSync(manifestPath, "utf8")); +} + +export function loadBackstageManifest(workspacePath: string): BackstageManifest | null { + const manifestPath = path.join(workspacePath, "backstage-manifest.json"); + if (!fs.existsSync(manifestPath)) return null; + return JSON.parse(fs.readFileSync(manifestPath, "utf8")); +} + +/** Build a version map from workspace and backstage manifests. */ +export function buildVersionMap( + workspaceManifest: WorkspaceManifest, + backstageManifest: BackstageManifest | null, +): Map { + const versionMap = new Map(); + + for (const pkg of workspaceManifest.packages) { + if (pkg.name && pkg.version) versionMap.set(pkg.name, pkg.version); + } + + if (backstageManifest) { + for (const pkg of backstageManifest.packages) { + if (!versionMap.has(pkg.name) && pkg.version) { + versionMap.set(pkg.name, pkg.version); + } + } + } + + return versionMap; +} diff --git a/prepare-sources/lib/modules/protocol-resolution/yarn-lock-blocks.ts b/prepare-sources/lib/modules/protocol-resolution/yarn-lock-blocks.ts new file mode 100644 index 0000000..9f15d6e --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/yarn-lock-blocks.ts @@ -0,0 +1,294 @@ +import type { BackstageManifest, WorkspaceManifest } from "../../manifest-types.ts"; +import type { Lockfile, LockfileBlock } from "../../yarn-lock-parser.ts"; +import { + blockLinkType, + hasDescriptorSpecifier, + hasNpmResolutionBlock, +} from "../../yarn-lock-helpers.ts"; +import { + buildResolutionBlock, + fetchNpmMetadataForBlock, + getDependenciesFromManifests, + mergeOptionalIntoDependencies, + type PackageLockMetadata, +} from "./yarn-lock-metadata.ts"; + +type ResolutionBlocksContext = { + lockfile: Lockfile; + versionMap: Map; + deletedWorkspaceBlocks: Map; + workspaceManifest: WorkspaceManifest; + backstageManifest: BackstageManifest | null; + log: (message: string) => void; + skipNpmFallback: boolean; +}; + +export type ResolutionBlocksParams = { + lockfile: Lockfile; + transformedPackages: Map; + versionMap: Map; + deletedWorkspaceBlocks: Map; + workspaceManifest: WorkspaceManifest; + backstageManifest: BackstageManifest | null; + log: (message: string) => void; + skipNpmFallback?: boolean; +}; + +export async function createMissingResolutionBlocks( + params: ResolutionBlocksParams, +): Promise { + const ctx: ResolutionBlocksContext = { + lockfile: params.lockfile, + versionMap: params.versionMap, + deletedWorkspaceBlocks: params.deletedWorkspaceBlocks, + workspaceManifest: params.workspaceManifest, + backstageManifest: params.backstageManifest, + log: params.log, + skipNpmFallback: params.skipNpmFallback ?? false, + }; + + let updateCount = 0; + const npmFetchFailures: string[] = []; + const inconsistentBlocks: string[] = []; + + for (const [packageName, version] of params.transformedPackages) { + // eslint-disable-next-line no-await-in-loop -- sequential by design: each block may depend on prior results + const result = await processOnePackage(ctx, packageName, version, inconsistentBlocks); + if (result === "skip") continue; + if (result === "fetch-failed") { + npmFetchFailures.push(`${packageName}@${version}`); + continue; + } + updateCount += result; + } + + throwOnFailures(npmFetchFailures, inconsistentBlocks); + return updateCount; +} + +function throwOnFailures(npmFetchFailures: string[], inconsistentBlocks: string[]): void { + const totalFailures = npmFetchFailures.length + inconsistentBlocks.length; + if (totalFailures > 0) { + const failedPkgs = [...npmFetchFailures, ...inconsistentBlocks]; + throw new Error(`Cannot produce consistent yarn.lock: ${failedPkgs.join(", ")}`); + } +} + +async function processOnePackage( + ctx: ResolutionBlocksContext, + packageName: string, + version: string, + inconsistentBlocks: string[], +): Promise { + if (hasNpmResolutionBlock(ctx.lockfile, packageName, version)) { + flagInconsistentSoftBlocks(ctx, packageName, version, inconsistentBlocks); + return "skip"; + } + + const resolved = await resolveMetadata(ctx, packageName, version); + if (resolved === "fetch-failed") return "fetch-failed"; + + const { metadata, fromCache } = resolved; + mergeOptionalIntoDependencies(metadata); + + return appendBlock(ctx, packageName, version, metadata, fromCache, inconsistentBlocks); +} + +function flagInconsistentSoftBlocks( + ctx: ResolutionBlocksContext, + packageName: string, + version: string, + inconsistentBlocks: string[], +): void { + const npmBlocks = ctx.lockfile.blocks.filter((b) => + b.descriptors.some((d) => d.includes(`${packageName}@npm:`)), + ); + for (const block of npmBlocks) { + if (blockLinkType(block) === "soft") { + ctx.log( + `yarn.lock: warning: surviving block for ${packageName} has linkType: soft — inconsistent with npm key`, + ); + inconsistentBlocks.push(`${packageName}@${version} (surviving block has linkType: soft)`); + } + } +} + +async function resolveMetadata( + ctx: ResolutionBlocksContext, + packageName: string, + version: string, +): Promise<{ metadata: PackageLockMetadata; fromCache: boolean } | "fetch-failed"> { + let metadata = await getDependenciesFromManifests( + packageName, + version, + ctx.workspaceManifest, + ctx.backstageManifest, + ctx.log, + ); + + let fromCache = true; + + if (metadata) { + const result = handleManifestMetadata(ctx, packageName, version, metadata); + if (result === "cleared") { + metadata = null; + fromCache = false; + } + } else { + fromCache = false; + } + + if (!metadata && !ctx.skipNpmFallback) { + ctx.log(`yarn.lock: fetching npm metadata for ${packageName}@${version}...`); + metadata = await fetchNpmMetadataForBlock(packageName, version, ctx.log); + } + + if (!metadata) { + return resolveEmptyMetadata(ctx, packageName, version); + } + + return { metadata, fromCache }; +} + +function handleManifestMetadata( + ctx: ResolutionBlocksContext, + packageName: string, + version: string, + metadata: PackageLockMetadata, +): "ok" | "cleared" { + const hasSubstance = + metadata.dependencies || + metadata.optionalDependencies || + metadata.peerDependencies || + metadata.bin; + + if (hasSubstance) { + ctx.log(`yarn.lock: using cached metadata for ${packageName}@${version}`); + return "ok"; + } + + if (ctx.skipNpmFallback) { + ctx.log( + `yarn.lock: manifest entry for ${packageName}@${version} has no deps — using empty metadata`, + ); + return "ok"; + } + + ctx.log( + `yarn.lock: manifest entry for ${packageName}@${version} has no deps — falling through to npm`, + ); + return "cleared"; +} + +function resolveEmptyMetadata( + ctx: ResolutionBlocksContext, + packageName: string, + version: string, +): { metadata: PackageLockMetadata; fromCache: boolean } | "fetch-failed" { + if (ctx.skipNpmFallback) { + ctx.log( + `yarn.lock: no metadata for local package ${packageName}@${version} — creating minimal block`, + ); + return { metadata: {}, fromCache: true }; + } + return "fetch-failed"; +} + +function appendBlock( + ctx: ResolutionBlocksContext, + packageName: string, + version: string, + metadata: PackageLockMetadata, + fromCache: boolean, + inconsistentBlocks: string[], +): number | "skip" { + const wasDeletedWorkspaceBlock = ctx.deletedWorkspaceBlocks.has(packageName); + const allSpecifiers = collectSpecifiers(ctx, packageName, version, wasDeletedWorkspaceBlock); + + if (allSpecifiers.length === 0) { + return handleNoSpecifiers( + ctx, + packageName, + version, + wasDeletedWorkspaceBlock, + inconsistentBlocks, + ); + } + + const uniqueSpecifiers = [...new Set(allSpecifiers)]; + const block = buildResolutionBlock( + packageName, + version, + uniqueSpecifiers, + metadata, + fromCache ? ctx.versionMap : null, + ); + ctx.lockfile.blocks.push(block); + + ctx.log( + `yarn.lock: created resolution block for ${uniqueSpecifiers.toSorted((a, b) => a.localeCompare(b)).join(", ")}`, + ); + return wasDeletedWorkspaceBlock ? 0 : 1; +} + +function collectSpecifiers( + ctx: ResolutionBlocksContext, + packageName: string, + version: string, + wasDeletedWorkspaceBlock: boolean, +): string[] { + const newSpecifier = `${packageName}@npm:^${version}`; + const specCandidates = [newSpecifier]; + if (wasDeletedWorkspaceBlock) { + const preserved = ctx.deletedWorkspaceBlocks.get(packageName); + if (preserved && preserved.length > 0) specCandidates.push(...preserved); + } + + const allSpecifiers: string[] = []; + for (const spec of specCandidates) { + if (!hasDescriptorSpecifier(ctx.lockfile, spec)) { + allSpecifiers.push(spec); + } else { + ctx.log(`yarn.lock: dropping specifier ${spec} — already satisfied by a surviving block`); + } + } + return allSpecifiers; +} + +function handleNoSpecifiers( + ctx: ResolutionBlocksContext, + packageName: string, + version: string, + wasDeletedWorkspaceBlock: boolean, + inconsistentBlocks: string[], +): "skip" { + if (wasDeletedWorkspaceBlock) { + warnIfSoftBlockSurvives(ctx, packageName, version, inconsistentBlocks); + } + ctx.log( + `yarn.lock: all specifiers for ${packageName}@${version} already satisfied — skipping block creation`, + ); + return "skip"; +} + +function warnIfSoftBlockSurvives( + ctx: ResolutionBlocksContext, + packageName: string, + version: string, + inconsistentBlocks: string[], +): void { + const softBlock = findSoftNpmBlock(ctx.lockfile, packageName); + if (softBlock) { + ctx.log( + `yarn.lock: warning: surviving block for ${packageName} has linkType: soft — may produce wrong dependency ranges`, + ); + inconsistentBlocks.push(`${packageName}@${version} (surviving block has linkType: soft)`); + } +} + +function findSoftNpmBlock(lockfile: Lockfile, packageName: string): LockfileBlock | undefined { + return lockfile.blocks.find( + (b) => + b.descriptors.some((d) => d.includes(`${packageName}@npm:`)) && blockLinkType(b) === "soft", + ); +} diff --git a/prepare-sources/lib/modules/protocol-resolution/yarn-lock-enrich.ts b/prepare-sources/lib/modules/protocol-resolution/yarn-lock-enrich.ts new file mode 100644 index 0000000..7784461 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/yarn-lock-enrich.ts @@ -0,0 +1,84 @@ +import type { Lockfile, LockfileBlock } from "../../yarn-lock-parser.ts"; +import { collectNpmDepReferences, findNpmBlocksForPackage } from "../../yarn-lock-helpers.ts"; +import { caretOrTildeSatisfies } from "./semver-range.ts"; + +export function normalizeCombinedKeysForLocalPackage( + lockfile: Lockfile, + packageName: string, + localPath: string, +): number { + const workspaceOnly = `${packageName}@workspace:${localPath}`; + let count = 0; + + for (const block of lockfile.blocks) { + const hasWorkspacePath = block.descriptors.includes(workspaceOnly); + if (!hasWorkspacePath || block.descriptors.length === 1) continue; + + const hasProtocolOrNpm = block.descriptors.some( + (d) => + d !== workspaceOnly && + (d.includes("@workspace:^") || + d.includes("@workspace:*") || + d.includes("@backstage:^") || + d.includes("@npm:")), + ); + if (hasProtocolOrNpm) { + block.descriptors = [workspaceOnly]; + count++; + } + } + + return count; +} + +export function enrichNpmBlockSpecifiers( + lockfile: Lockfile, + log: (message: string) => void, +): number { + const allRefs = collectNpmDepReferences(lockfile); + let enrichCount = 0; + + for (const [packageName, ranges] of allRefs) { + const npmBlocks = findNpmBlocksForPackage(lockfile, packageName); + if (npmBlocks.length === 0) { + log(`yarn.lock: warning: no npm block found for ${packageName} — cannot enrich specifiers`); + continue; + } + enrichCount += enrichRangesForPackage(lockfile, packageName, ranges, npmBlocks, log); + } + + return enrichCount; +} + +function enrichRangesForPackage( + lockfile: Lockfile, + packageName: string, + ranges: Set, + npmBlocks: Array<{ block: LockfileBlock; version: string }>, + log: (message: string) => void, +): number { + let count = 0; + + for (const range of ranges) { + const specifier = `${packageName}@npm:${range}`; + if (lockfile.blocks.some((b) => b.descriptors.includes(specifier))) continue; + + const prefix: "^" | "~" = range.startsWith("~") ? "~" : "^"; + const rangeVersion = range.substring(1); + const target = npmBlocks.find((b) => caretOrTildeSatisfies(b.version, prefix, rangeVersion)); + if (!target) { + log( + `yarn.lock: warning: no block for ${packageName} satisfies ${range} — skipping specifier enrichment`, + ); + continue; + } + + if (!target.block.descriptors.includes(specifier)) { + target.block.descriptors.push(specifier); + target.block.descriptors.sort((a, b) => a.localeCompare(b)); + count++; + } + } + + return count; +} diff --git a/prepare-sources/lib/modules/protocol-resolution/yarn-lock-metadata.ts b/prepare-sources/lib/modules/protocol-resolution/yarn-lock-metadata.ts new file mode 100644 index 0000000..02e11d7 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/yarn-lock-metadata.ts @@ -0,0 +1,360 @@ +import type { BackstageManifest, WorkspaceManifest } from "../../manifest-types.ts"; +import type { LockfileBlock, MapField, NestedMapField } from "../../yarn-lock-parser.ts"; +import { buildMapField } from "../../yarn-lock-helpers.ts"; +import { fetchNpmPackageMetadata } from "./npm-metadata.ts"; + +export type PackageLockMetadata = { + dependencies?: Record | null; + optionalDependencies?: Record | null; + dependenciesMeta?: Record> | null; + peerDependencies?: Record | null; + peerDependenciesMeta?: Record> | null; + bin?: Record | string | null; +}; + +function hasProtocolRefs(deps: Record | null | undefined): boolean { + return ( + deps != null && + Object.values(deps).some((v) => v.startsWith("workspace:") || v === "backstage:^") + ); +} + +function replaceProtocolRanges( + target: Record | null | undefined, + source: Record | null | undefined, +): void { + if (!target || !source) return; + for (const [name, range] of Object.entries(target)) { + if (range.startsWith("workspace:") || range === "backstage:^") { + if (source[name]) target[name] = source[name]; + } + } +} + +async function getNpmPublishedRanges( + packageName: string, + version: string, + backstageManifest: BackstageManifest | null, + log: (message: string) => void, +): Promise | null> { + if (backstageManifest) { + const pkg = backstageManifest.packages.find( + (p) => p.name === packageName && p.version === version, + ); + if (pkg) { + return { + dependencies: pkg.dependencies ?? null, + peerDependencies: pkg.peerDependencies ?? null, + }; + } + } + + const metadata = await fetchNpmPackageMetadata(packageName, version, log); + if (!metadata) return null; + return { + dependencies: metadata.dependencies ?? null, + peerDependencies: metadata.peerDependencies ?? null, + }; +} + +export async function getDependenciesFromManifests( + packageName: string, + version: string, + workspaceManifest: WorkspaceManifest, + backstageManifest: BackstageManifest | null, + log: (message: string) => void, + options: { skipWorkspaceManifest?: boolean } = {}, +): Promise { + if (!options.skipWorkspaceManifest) { + const pkg = workspaceManifest.packages.find((p) => p.name === packageName); + if (pkg) { + const result: PackageLockMetadata = { + dependencies: pkg.dependencies ? { ...pkg.dependencies } : null, + optionalDependencies: pkg.optionalDependencies ?? null, + peerDependencies: pkg.peerDependencies ? { ...pkg.peerDependencies } : null, + peerDependenciesMeta: pkg.peerDependenciesMeta ?? null, + bin: pkg.bin ?? null, + }; + + if (hasProtocolRefs(result.dependencies) || hasProtocolRefs(result.peerDependencies)) { + const npmRanges = await getNpmPublishedRanges(packageName, version, backstageManifest, log); + if (npmRanges) { + replaceProtocolRanges(result.dependencies, npmRanges.dependencies); + replaceProtocolRanges(result.peerDependencies, npmRanges.peerDependencies); + } + } + return result; + } + } + + if (backstageManifest) { + const pkg = backstageManifest.packages.find( + (p) => p.name === packageName && p.version === version, + ); + if (pkg) { + return { + dependencies: pkg.dependencies ?? null, + optionalDependencies: pkg.optionalDependencies ?? null, + peerDependencies: pkg.peerDependencies ?? null, + peerDependenciesMeta: pkg.peerDependenciesMeta ?? null, + bin: pkg.bin ?? null, + }; + } + } + + return null; +} + +export function resolveMonorepoProtocol( + version: string, + name: string, + versionMap: Map | null, +): string | null { + if (!version.startsWith("workspace:") && version !== "backstage:^") return null; + const mapped = versionMap?.get(name); + if (mapped === undefined) return null; + const rangeSpecifier = version.replace(/^workspace:/, "").replace(/^backstage:/, ""); + const prefix = rangeSpecifier === "^" || rangeSpecifier === "~" ? rangeSpecifier : ""; + return `${prefix}${mapped}`; +} + +export async function fetchNpmMetadataForBlock( + packageName: string, + version: string, + log: (message: string) => void, +): Promise { + const npmMetadata = await fetchNpmPackageMetadata(packageName, version, log); + if (!npmMetadata) return null; + + let mergedDeps = npmMetadata.dependencies ? { ...npmMetadata.dependencies } : null; + let depsMeta: Record> | null = null; + + if (npmMetadata.optionalDependencies) { + if (!mergedDeps) mergedDeps = {}; + for (const [optName, optRange] of Object.entries(npmMetadata.optionalDependencies)) { + mergedDeps[optName] = optRange; + } + depsMeta = {}; + for (const optName of Object.keys(npmMetadata.optionalDependencies)) { + depsMeta[optName] = { optional: true }; + } + } + + return { + dependencies: mergedDeps, + dependenciesMeta: depsMeta, + peerDependencies: npmMetadata.peerDependencies ?? null, + peerDependenciesMeta: npmMetadata.peerDependenciesMeta ?? null, + bin: npmMetadata.bin ?? null, + }; +} + +export function mergeOptionalIntoDependencies(metadata: PackageLockMetadata): void { + if (!metadata.optionalDependencies) return; + if (!metadata.dependencies) metadata.dependencies = {}; + if (!metadata.dependenciesMeta) metadata.dependenciesMeta = {}; + for (const [optName, optRange] of Object.entries(metadata.optionalDependencies)) { + metadata.dependencies[optName] = optRange; + metadata.dependenciesMeta[optName] = { optional: true }; + } + delete metadata.optionalDependencies; +} + +// --------------------------------------------------------------------------- +// Structured lockfile block builders (used with yarn-lock-parser) +// --------------------------------------------------------------------------- + +export function buildDependenciesMapField( + deps: Record, + versionMap: Map | null, +): { field: MapField | null; emittedKeys: Set } { + const entries: Record = {}; + const emittedKeys = new Set(); + + for (const [name, version] of Object.entries(deps).toSorted((a, b) => a[0].localeCompare(b[0]))) { + const resolved = resolveMonorepoProtocol(version, name, versionMap); + let npmVersion: string; + if (resolved !== null) { + npmVersion = `npm:${resolved}`; + } else if (version.startsWith("workspace:") || version === "backstage:^") { + continue; + } else if (version.startsWith("npm:")) { + npmVersion = version; + } else { + npmVersion = `npm:${version}`; + } + entries[`"${name}"`] = `"${npmVersion}"`; + emittedKeys.add(name); + } + + if (Object.keys(entries).length === 0) return { field: null, emittedKeys }; + return { field: buildMapField(entries), emittedKeys }; +} + +function buildPeerDependenciesMapField( + peerDeps: Record, + versionMap: Map | null, +): MapField | null { + const entries: Record = {}; + for (const [name, version] of Object.entries(peerDeps).toSorted((a, b) => + a[0].localeCompare(b[0]), + )) { + const resolved = resolveMonorepoProtocol(version, name, versionMap); + entries[`"${name}"`] = `"${resolved !== null ? resolved : version}"`; + } + if (Object.keys(entries).length === 0) return null; + return buildMapField(entries); +} + +function buildDependenciesMetaField( + depsMeta: Record>, +): NestedMapField | null { + const entries: Record> = {}; + for (const [name, meta] of Object.entries(depsMeta).toSorted((a, b) => + a[0].localeCompare(b[0]), + )) { + entries[name] = {}; + for (const [key, value] of Object.entries(meta)) { + entries[name][key] = String(value); + } + } + if (Object.keys(entries).length === 0) return null; + return { kind: "nested-map", entries }; +} + +function buildPeerDependenciesMetaField( + peerDepsMeta: Record>, +): NestedMapField | null { + const entries: Record> = {}; + for (const [name, meta] of Object.entries(peerDepsMeta).toSorted((a, b) => + a[0].localeCompare(b[0]), + )) { + const entry: Record = {}; + entries[`"${name}"`] = entry; + for (const [key, value] of Object.entries(meta)) { + entry[key] = String(value); + } + } + if (Object.keys(entries).length === 0) return null; + return { kind: "nested-map", entries }; +} + +function buildBinMapField( + bin: Record | string, + packageName: string, +): MapField | null { + let binObj: Record; + if (typeof bin === "string") { + const unscopedName = packageName.replace(/^@[^/]+\//, ""); + binObj = { [unscopedName]: bin }; + } else { + binObj = bin; + } + if (Object.keys(binObj).length === 0) return null; + const entries: Record = {}; + for (const [name, binPath] of Object.entries(binObj).toSorted((a, b) => + a[0].localeCompare(b[0]), + )) { + entries[name] = binPath; + } + return buildMapField(entries); +} + +/** Build a complete npm resolution block for appending to a parsed lockfile. */ +export function buildResolutionBlock( + packageName: string, + version: string, + descriptors: string[], + metadata: PackageLockMetadata, + versionMap: Map | null, +): LockfileBlock { + const fields: LockfileBlock["fields"] = { + version: { kind: "scalar", raw: version }, + resolution: { kind: "scalar", raw: `"${packageName}@npm:${version}"` }, + }; + + let emittedDepKeys: Set | null = null; + if (metadata.dependencies) { + const depsResult = buildDependenciesMapField(metadata.dependencies, versionMap); + if (depsResult.field) { + fields.dependencies = depsResult.field; + emittedDepKeys = depsResult.emittedKeys; + } + } + if (metadata.peerDependencies) { + const peersField = buildPeerDependenciesMapField(metadata.peerDependencies, versionMap); + if (peersField) fields.peerDependencies = peersField; + } + if (metadata.dependenciesMeta) { + let filteredMeta = metadata.dependenciesMeta; + if (emittedDepKeys) { + filteredMeta = {}; + for (const [key, value] of Object.entries(metadata.dependenciesMeta)) { + if (emittedDepKeys.has(key)) filteredMeta[key] = value; + } + } + const metaField = buildDependenciesMetaField(filteredMeta); + if (metaField) fields.dependenciesMeta = metaField; + } + if (metadata.peerDependenciesMeta) { + const peersMetaField = buildPeerDependenciesMetaField(metadata.peerDependenciesMeta); + if (peersMetaField) fields.peerDependenciesMeta = peersMetaField; + } + if (metadata.bin) { + const binField = buildBinMapField(metadata.bin, packageName); + if (binField) fields.bin = binField; + } + + fields.languageName = { kind: "scalar", raw: "node" }; + fields.linkType = { kind: "scalar", raw: "hard" }; + + return { + descriptors: [...descriptors].toSorted((a, b) => a.localeCompare(b)), + fields, + }; +} + +/** Build a soft-linked workspace block (e.g. type-shims pre-wire entry). */ +export function buildWorkspaceSoftBlock( + packageName: string, + workspacePath: string, + deps: Record, + devDeps: Record, +): LockfileBlock { + const fields: LockfileBlock["fields"] = { + version: { kind: "scalar", raw: "0.0.0-use.local" }, + resolution: { + kind: "scalar", + raw: `"${packageName}@workspace:${workspacePath}"`, + }, + languageName: { kind: "scalar", raw: "unknown" }, + linkType: { kind: "scalar", raw: "soft" }, + }; + + if (Object.keys(deps).length > 0) { + const entries: Record = {}; + for (const [name, version] of Object.entries(deps).toSorted((a, b) => + a[0].localeCompare(b[0]), + )) { + const npmVersion = version.startsWith("npm:") ? version : `npm:${version}`; + entries[`"${name}"`] = `"${npmVersion}"`; + } + fields.dependencies = buildMapField(entries); + } + + if (Object.keys(devDeps).length > 0) { + const entries: Record = {}; + for (const [name, version] of Object.entries(devDeps).toSorted((a, b) => + a[0].localeCompare(b[0]), + )) { + const npmVersion = version.startsWith("npm:") ? version : `npm:${version}`; + entries[`"${name}"`] = `"${npmVersion}"`; + } + fields.devDependencies = buildMapField(entries); + } + + return { + descriptors: [`${packageName}@workspace:${workspacePath}`], + fields, + }; +} diff --git a/prepare-sources/lib/modules/protocol-resolution/yarn-lock-update.ts b/prepare-sources/lib/modules/protocol-resolution/yarn-lock-update.ts new file mode 100644 index 0000000..3e921b0 --- /dev/null +++ b/prepare-sources/lib/modules/protocol-resolution/yarn-lock-update.ts @@ -0,0 +1,447 @@ +import fs from "node:fs"; +import path from "node:path"; +import type { BackstageManifest, WorkspaceManifest } from "../../manifest-types.ts"; +import type { Lockfile, LockfileBlock } from "../../yarn-lock-parser.ts"; +import { parseLockfile, serializeLockfile } from "../../yarn-lock-parser.ts"; +import { + blockHasStaleWorkspacePath, + blockHasWorkspaceProtocol, + collectNpmDepReferences, + extractNpmSpecifiers, + findLocalPackagePaths, + packageNameFromDescriptor, + hasNpmSpecifierBlock, + replaceProtocolDepValues, + unquote, + workspaceProtocolPackageName, +} from "../../yarn-lock-helpers.ts"; +import { createMissingResolutionBlocks } from "./yarn-lock-blocks.ts"; +import { + enrichNpmBlockSpecifiers, + normalizeCombinedKeysForLocalPackage, +} from "./yarn-lock-enrich.ts"; +import { findPackageVersion } from "./utils.ts"; + +export type YarnLockUpdateResult = { + updates: number; +}; + +type LockUpdateState = { + lockfile: Lockfile; + versionMap: Map; + localPackagePaths: Map; + transformedNonLocalPackages: Map; + deletedWorkspaceBlocks: Map; + deletedStalePathPackages: Set; + processedPackages: Set; + workspacePath: string; + log: (message: string) => void; +}; + +/** + * Rewrite yarn.lock: delete stale workspace blocks, convert protocol refs to npm, + * recreate missing resolution blocks, enrich specifiers. + */ +export async function updateYarnLock( + yarnLockPath: string, + versionMap: Map, + workspaceManifest: WorkspaceManifest, + backstageManifest: BackstageManifest | null, + workspacePath: string, + log: (message: string) => void, +): Promise { + if (!fs.existsSync(yarnLockPath)) { + throw new Error(`yarn.lock not found at ${yarnLockPath}`); + } + + const yarnLockDir = path.dirname(yarnLockPath); + const lockfile = parseLockfile(fs.readFileSync(yarnLockPath, "utf8")); + const state: LockUpdateState = { + lockfile, + versionMap, + localPackagePaths: findLocalPackagePaths(lockfile, yarnLockDir), + transformedNonLocalPackages: new Map(), + deletedWorkspaceBlocks: new Map(), + deletedStalePathPackages: new Set(), + processedPackages: new Set(), + workspacePath, + log, + }; + + let updateCount = 0; + updateCount += deleteStaleAndNonLocalWorkspaceBlocks(state, yarnLockDir); + pruneStaleFromDeletedBlocks(state); + seedTransformedFromDeleted(state); + updateCount += applyVersionMapPackageUpdates(state); + + const { remainingPackages, unresolvedPackages } = collectRemainingProtocolRefs(state); + logUnresolvedPackages(state, unresolvedPackages); + updateCount += applyRemainingPackageUpdates(state, remainingPackages); + + updateCount += await createMissingResolutionBlocks({ + lockfile, + transformedPackages: state.transformedNonLocalPackages, + versionMap, + deletedWorkspaceBlocks: state.deletedWorkspaceBlocks, + workspaceManifest, + backstageManifest, + log, + }); + + const localPackagesForNpmBlocks = new Map(); + for (const [pkgName] of state.localPackagePaths) { + const version = versionMap.get(pkgName); + if (version) localPackagesForNpmBlocks.set(pkgName, version); + } + if (localPackagesForNpmBlocks.size > 0) { + updateCount += await createMissingResolutionBlocks({ + lockfile, + transformedPackages: localPackagesForNpmBlocks, + versionMap, + deletedWorkspaceBlocks: state.deletedWorkspaceBlocks, + workspaceManifest, + backstageManifest, + log, + skipNpmFallback: true, + }); + } + + const alreadyProcessed = new Set([ + ...state.transformedNonLocalPackages.keys(), + ...localPackagesForNpmBlocks.keys(), + ]); + updateCount += await resolveDanglingDeps( + state, + workspaceManifest, + backstageManifest, + 1, + alreadyProcessed, + ); + + const enriched = enrichNpmBlockSpecifiers(lockfile, log); + if (enriched > 0) { + log(`yarn.lock: enriched ${enriched} npm block specifier(s)`); + updateCount += enriched; + } + + if (updateCount > 0) { + fs.writeFileSync(yarnLockPath, serializeLockfile(lockfile)); + } + + log(`yarn.lock: ${updateCount} updates applied`); + return { updates: updateCount }; +} + +/** Pass 1: remove stale-path and scrubbed-package workspace protocol blocks. */ +function deleteStaleAndNonLocalWorkspaceBlocks( + state: LockUpdateState, + yarnLockDir: string, +): number { + let updateCount = 0; + const survivingBlocks: LockfileBlock[] = []; + + for (const block of state.lockfile.blocks) { + const staleDeleted = tryDeleteStalePathBlock(state, block, yarnLockDir); + if (staleDeleted !== null) { + updateCount += staleDeleted; + continue; + } + + const nonLocalDeleted = tryDeleteNonLocalWorkspaceBlock(state, block); + if (nonLocalDeleted !== null) { + updateCount += nonLocalDeleted; + continue; + } + + survivingBlocks.push(block); + } + + state.lockfile.blocks = survivingBlocks; + return updateCount; +} + +/** @returns update count if deleted, or null if the block should be kept. */ +function tryDeleteStalePathBlock( + state: LockUpdateState, + block: LockfileBlock, + yarnLockDir: string, +): number | null { + if (!blockHasStaleWorkspacePath(block, yarnLockDir)) return null; + const pkgName = + workspaceProtocolPackageName(block) ?? packageNameFromDescriptor(block.descriptors[0] ?? ""); + if (!pkgName) return null; + + state.deletedStalePathPackages.add(pkgName); + state.log(`yarn.lock: deleted stale workspace block for ${pkgName}`); + return 1; +} + +/** @returns update count if deleted, or null if the block should be kept. */ +function tryDeleteNonLocalWorkspaceBlock( + state: LockUpdateState, + block: LockfileBlock, +): number | null { + if (!blockHasWorkspaceProtocol(block)) return null; + const pkgName = workspaceProtocolPackageName(block); + if (!pkgName || state.localPackagePaths.has(pkgName)) return null; + + if (state.deletedStalePathPackages.has(pkgName)) { + state.log(`yarn.lock: deleted workspace:^ block for stale package ${pkgName}`); + return 1; + } + + if (!state.versionMap.has(pkgName)) { + state.log(`yarn.lock: warning: no version found for ${pkgName} in version map`); + return null; + } + + const npmSpecifiers = extractNpmSpecifiers(block, pkgName); + const existing = state.deletedWorkspaceBlocks.get(pkgName) ?? []; + state.deletedWorkspaceBlocks.set(pkgName, [...existing, ...npmSpecifiers]); + state.log( + `yarn.lock: deleted workspace block for ${pkgName}` + + (npmSpecifiers.length ? ` (preserving npm specifiers: ${npmSpecifiers.join(", ")})` : ""), + ); + return 1; +} + +function pruneStaleFromDeletedBlocks(state: LockUpdateState): void { + for (const stalePkg of state.deletedStalePathPackages) { + if (!state.deletedWorkspaceBlocks.has(stalePkg)) continue; + state.log(`yarn.lock: removing ${stalePkg} from workspace block recreation — package is stale`); + state.deletedWorkspaceBlocks.delete(stalePkg); + } +} + +function seedTransformedFromDeleted(state: LockUpdateState): void { + for (const [pkgName] of state.deletedWorkspaceBlocks) { + const version = state.versionMap.get(pkgName); + if (version) state.transformedNonLocalPackages.set(pkgName, version); + } +} + +/** Pass 2: rewrite protocol deps / normalize combined keys for version-map packages. */ +function applyVersionMapPackageUpdates(state: LockUpdateState): number { + let updateCount = 0; + + for (const [packageName, newVersion] of state.versionMap) { + state.processedPackages.add(packageName); + updateCount += updateOneVersionMapPackage(state, packageName, newVersion); + } + + return updateCount; +} + +function updateOneVersionMapPackage( + state: LockUpdateState, + packageName: string, + newVersion: string, +): number { + const localPath = state.localPackagePaths.get(packageName); + if (localPath === undefined) { + const replaced = replaceProtocolDepValues(state.lockfile, packageName, newVersion); + if (replaced <= 0) return 0; + state.log(`yarn.lock: updated dependency ${packageName} to npm:${newVersion}`); + state.transformedNonLocalPackages.set(packageName, newVersion); + return replaced; + } + + const normalized = normalizeCombinedKeysForLocalPackage(state.lockfile, packageName, localPath); + if (normalized <= 0) return 0; + state.log(`yarn.lock: normalized combined key for local package ${packageName}`); + return normalized; +} + +/** Pass 3 scan: find leftover workspace:/backstage:^ refs not yet processed. */ +function collectRemainingProtocolRefs(state: LockUpdateState): { + remainingPackages: Map; + unresolvedPackages: string[]; +} { + const remainingPackages = new Map(); + const unresolvedPackages: string[] = []; + + for (const block of state.lockfile.blocks) { + collectRefsFromDepMaps(state, block, remainingPackages, unresolvedPackages); + collectRefFromWorkspaceBlockKey(state, block, remainingPackages, unresolvedPackages); + } + + return { remainingPackages, unresolvedPackages }; +} + +function collectRefsFromDepMaps( + state: LockUpdateState, + block: LockfileBlock, + remainingPackages: Map, + unresolvedPackages: string[], +): void { + for (const field of Object.values(block.fields)) { + if (field.kind !== "map") continue; + for (const [depName, rawValue] of Object.entries(field.entries)) { + const name = unquote(depName); + const value = unquote(rawValue); + if (!/^(?:workspace:[*^]?|backstage:\^)$/.exec(value)) continue; + if (state.processedPackages.has(name) || remainingPackages.has(name)) continue; + recordResolvedOrUnresolved(state, name, remainingPackages, unresolvedPackages); + } + } +} + +function collectRefFromWorkspaceBlockKey( + state: LockUpdateState, + block: LockfileBlock, + remainingPackages: Map, + unresolvedPackages: string[], +): void { + if (!blockHasWorkspaceProtocol(block)) return; + const pkgName = workspaceProtocolPackageName(block); + if (!pkgName) return; + if (state.processedPackages.has(pkgName) || remainingPackages.has(pkgName)) return; + recordResolvedOrUnresolved(state, pkgName, remainingPackages, unresolvedPackages); +} + +function recordResolvedOrUnresolved( + state: LockUpdateState, + name: string, + remainingPackages: Map, + unresolvedPackages: string[], +): void { + const resolved = state.versionMap.get(name) ?? findPackageVersion(name, state.workspacePath); + if (resolved) { + remainingPackages.set(name, resolved); + return; + } + if (!unresolvedPackages.includes(name)) unresolvedPackages.push(name); +} + +function logUnresolvedPackages(state: LockUpdateState, unresolvedPackages: string[]): void { + if (unresolvedPackages.length === 0) return; + state.log( + `yarn.lock: warning: ${unresolvedPackages.length} package(s) with workspace:/backstage:^ references could not be resolved`, + ); + for (const pkg of unresolvedPackages) { + state.log(` - ${pkg} (not in versionMap, not found on disk)`); + } +} + +/** Pass 3 apply: rewrite remaining refs and delete leftover workspace blocks. */ +function applyRemainingPackageUpdates( + state: LockUpdateState, + remainingPackages: Map, +): number { + let updateCount = 0; + for (const [packageName, version] of remainingPackages) { + updateCount += applyOneRemainingPackage(state, packageName, version); + } + return updateCount; +} + +function applyOneRemainingPackage( + state: LockUpdateState, + packageName: string, + version: string, +): number { + let updateCount = 0; + + const replaced = replaceProtocolDepValues(state.lockfile, packageName, version); + if (replaced > 0) { + updateCount += replaced; + state.log( + `yarn.lock: updated dependency ${packageName} to npm:^${version} (from remaining scan)`, + ); + if (!state.localPackagePaths.has(packageName)) { + state.transformedNonLocalPackages.set(packageName, version); + } + } + + updateCount += deleteRemainingWorkspaceBlockIfNeeded(state, packageName, version); + return updateCount; +} + +function deleteRemainingWorkspaceBlockIfNeeded( + state: LockUpdateState, + packageName: string, + version: string, +): number { + if (state.localPackagePaths.has(packageName)) return 0; + if (state.deletedStalePathPackages.has(packageName)) return 0; + + const blocksToRemove = state.lockfile.blocks.filter((block) => { + if (!blockHasWorkspaceProtocol(block)) return false; + return workspaceProtocolPackageName(block) === packageName; + }); + if (blocksToRemove.length === 0) return 0; + + const npmSpecifiers = blocksToRemove.flatMap((b) => extractNpmSpecifiers(b, packageName)); + const existing = state.deletedWorkspaceBlocks.get(packageName) ?? []; + state.deletedWorkspaceBlocks.set(packageName, [...existing, ...npmSpecifiers]); + state.transformedNonLocalPackages.set(packageName, version); + state.lockfile.blocks = state.lockfile.blocks.filter((b) => !blocksToRemove.includes(b)); + state.log( + `yarn.lock: deleted remaining workspace block for ${packageName}` + + (npmSpecifiers.length ? ` (preserving npm specifiers: ${npmSpecifiers.join(", ")})` : ""), + ); + return 1; +} + +/** Multi-pass: create npm blocks for deps introduced by previously created blocks. */ +async function resolveDanglingDeps( + state: LockUpdateState, + workspaceManifest: WorkspaceManifest, + backstageManifest: BackstageManifest | null, + pass: number, + alreadyProcessed: Set, +): Promise { + if (pass > 10) return 0; + + const danglingPackages = collectDanglingPackages(state, alreadyProcessed); + if (danglingPackages.size === 0) return 0; + + state.log( + `yarn.lock: dangling-dep pass ${pass}: creating blocks for ${danglingPackages.size} package(s)`, + ); + const created = await createMissingResolutionBlocks({ + lockfile: state.lockfile, + transformedPackages: danglingPackages, + versionMap: state.versionMap, + deletedWorkspaceBlocks: state.deletedWorkspaceBlocks, + workspaceManifest, + backstageManifest, + log: state.log, + }); + + for (const name of danglingPackages.keys()) { + alreadyProcessed.add(name); + } + + return ( + created + + (await resolveDanglingDeps( + state, + workspaceManifest, + backstageManifest, + pass + 1, + alreadyProcessed, + )) + ); +} + +function collectDanglingPackages( + state: LockUpdateState, + alreadyProcessed: Set, +): Map { + const danglingPackages = new Map(); + const allRefs = collectNpmDepReferences(state.lockfile); + + for (const [depName, ranges] of allRefs) { + if (alreadyProcessed.has(depName)) continue; + const version = state.versionMap.get(depName); + if (version === undefined) continue; + + const needsBlock = [...ranges].some( + (range) => !hasNpmSpecifierBlock(state.lockfile, depName, range), + ); + if (needsBlock) danglingPackages.set(depName, version); + } + + return danglingPackages; +} diff --git a/prepare-sources/lib/yarn-lock-helpers.ts b/prepare-sources/lib/yarn-lock-helpers.ts new file mode 100644 index 0000000..fc4df21 --- /dev/null +++ b/prepare-sources/lib/yarn-lock-helpers.ts @@ -0,0 +1,216 @@ +/** + * Shared helpers for mutating parsed Yarn Berry lockfiles. + * Used by `protocol-resolution`, `package-cleanup`, and `validate`. + */ + +import fs from "node:fs"; +import path from "node:path"; +import type { Lockfile, LockfileBlock, MapField } from "./yarn-lock-parser.ts"; +import { getScalar } from "./yarn-lock-parser.ts"; + +/** Strip surrounding quotes from a yarn.lock scalar or map value. */ +export function unquote(value: string): string { + return value.replace(/^"|"$/g, ""); +} + +/** Extract the npm package name from a lockfile descriptor (e.g. `@foo/bar@npm:^1.0`). */ +export function packageNameFromDescriptor(descriptor: string): string | null { + const match = /^((?:@[^@/]+\/)?[^@]+)@/.exec(descriptor); + return match?.[1] ?? null; +} + +export function descriptorHasWorkspaceProtocol(descriptor: string): boolean { + return ( + descriptor.includes("@workspace:^") || + descriptor.includes("@workspace:*") || + descriptor.includes("@workspace:~") || + descriptor.includes("@backstage:^") + ); +} + +/** Relative workspace path from a `package@workspace:path` descriptor, or null. */ +export function descriptorWorkspacePath(descriptor: string): string | null { + const match = /@workspace:([^",^*][^",]*)/.exec(descriptor); + const wsPath = match?.[1]; + if (!wsPath || wsPath === ".") return null; + return wsPath; +} + +/** Map package name → workspace-relative path for packages whose dirs exist on disk. */ +export function findLocalPackagePaths( + lockfile: Lockfile, + yarnLockDir: string, +): Map { + const localPackagePaths = new Map(); + + for (const block of lockfile.blocks) { + for (const descriptor of block.descriptors) { + const wsPath = descriptorWorkspacePath(descriptor); + if (!wsPath) continue; + const pkgName = packageNameFromDescriptor(descriptor); + if (!pkgName) continue; + const fullPath = path.join(yarnLockDir, wsPath); + if (fs.existsSync(fullPath)) { + localPackagePaths.set(pkgName, wsPath); + } + } + } + + return localPackagePaths; +} + +/** First package name in a block matching a workspace/backstage protocol descriptor. */ +export function workspaceProtocolPackageName(block: LockfileBlock): string | null { + for (const descriptor of block.descriptors) { + if (!descriptorHasWorkspaceProtocol(descriptor)) continue; + const match = /^(?:@[^@/]+\/)?[^@",\s]+@(?:workspace:[*^~]|backstage:\^)/.exec(descriptor); + + if (match) { + const name = packageNameFromDescriptor(descriptor); + if (name) return name; + } + } + return null; +} + +export function blockHasStaleWorkspacePath(block: LockfileBlock, yarnLockDir: string): boolean { + for (const descriptor of block.descriptors) { + const wsPath = descriptorWorkspacePath(descriptor); + if (!wsPath) continue; + const fullPath = path.join(yarnLockDir, wsPath); + if (!fs.existsSync(fullPath)) return true; + } + return false; +} + +export function blockHasWorkspaceProtocol(block: LockfileBlock): boolean { + return block.descriptors.some(descriptorHasWorkspaceProtocol); +} + +/** npm specifiers (`pkg@npm:…`) preserved from a block's combined key. */ +export function extractNpmSpecifiers(block: LockfileBlock, packageName: string): string[] { + const specifiers: string[] = []; + for (const descriptor of block.descriptors) { + const escaped = packageName.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`); + const pattern = new RegExp(`${escaped}@npm:[^",]+`, "g"); + let match: RegExpExecArray | null; + while ((match = pattern.exec(descriptor)) !== null) { + specifiers.push(match[0]); + } + } + return specifiers; +} + +/** Whether any block key includes `package@npm:^version` (or exact version). */ +export function hasNpmResolutionBlock( + lockfile: Lockfile, + packageName: string, + version: string, +): boolean { + const escapedName = packageName.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`); + const escapedVersion = version.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`); + const pattern = new RegExp(String.raw`${escapedName}@npm:\^?${escapedVersion}(?=[",])`); + return lockfile.blocks.some((block) => block.descriptors.some((d) => pattern.test(d))); +} + +/** Whether any block descriptor includes `package@npm:range` (range includes ^ or ~). */ +export function hasNpmSpecifierBlock( + lockfile: Lockfile, + packageName: string, + range: string, +): boolean { + const specifier = `${packageName}@npm:${range}`; + return lockfile.blocks.some((block) => block.descriptors.some((d) => d.includes(specifier))); +} + +/** Blocks whose descriptors reference the given package name with npm specifiers. */ +export function findNpmBlocksForPackage( + lockfile: Lockfile, + packageName: string, +): Array<{ block: LockfileBlock; version: string }> { + const results: Array<{ block: LockfileBlock; version: string }> = []; + + for (const block of lockfile.blocks) { + const hasNpmDescriptor = block.descriptors.some((d) => d.includes(`${packageName}@npm:`)); + if (!hasNpmDescriptor) continue; + const version = getScalar(block, "version"); + if (version) results.push({ block, version }); + } + + return results; +} + +/** Whether a block key already contains the exact descriptor specifier. */ +export function hasDescriptorSpecifier(lockfile: Lockfile, specifier: string): boolean { + return lockfile.blocks.some((block) => block.descriptors.includes(specifier)); +} + +/** Iterate all dependency-map entries across every block. */ +export function forEachDependencyEntry( + lockfile: Lockfile, + callback: (block: LockfileBlock, mapField: MapField, depName: string, rawValue: string) => void, +): void { + for (const block of lockfile.blocks) { + for (const field of Object.values(block.fields)) { + if (field.kind !== "map") continue; + for (const [depName, rawValue] of Object.entries(field.entries)) { + callback(block, field, depName, rawValue); + } + } + } +} + +/** Replace `workspace:^` / `backstage:^` dep values with `npm:^version` in all map fields. */ +export function replaceProtocolDepValues( + lockfile: Lockfile, + packageName: string, + version: string, +): number { + let count = 0; + const workspacePattern = /^(?:workspace:[*^]?|backstage:\^)$/; + const target = `"npm:^${version}"`; + + forEachDependencyEntry(lockfile, (_block, mapField, depName, rawValue) => { + if (depName !== `"${packageName}"` && depName !== packageName) return; + const unquoted = unquote(rawValue); + if (workspacePattern.test(unquoted)) { + mapField.entries[depName] = target; + count++; + } + }); + + return count; +} + +/** Collect npm caret/tilde ranges referenced in dependency map bodies. */ +export function collectNpmDepReferences(lockfile: Lockfile): Map> { + const allRefs = new Map>(); + + forEachDependencyEntry(lockfile, (_block, _mapField, depName, rawValue) => { + const name = unquote(depName); + const unquoted = unquote(rawValue); + const match = /^npm:([\^~])(.+)$/.exec(unquoted); + if (!match) return; + let refs = allRefs.get(name); + if (!refs) { + refs = new Set(); + allRefs.set(name, refs); + } + refs.add(`${match[1]}${match[2]}`); + }); + + return allRefs; +} + +/** Build a sorted map field from lockfile-formatted `"key": "value"` entries. */ +export function buildMapField(entries: Record): MapField { + const sorted: Record = {}; + for (const [key, value] of Object.entries(entries).toSorted((a, b) => a[0].localeCompare(b[0]))) { + sorted[key] = value; + } + return { kind: "map", entries: sorted }; +} + +export function blockLinkType(block: LockfileBlock): string | undefined { + return getScalar(block, "linkType"); +} diff --git a/prepare-sources/tsconfig.json b/prepare-sources/tsconfig.json index 8131693..afdbaca 100644 --- a/prepare-sources/tsconfig.json +++ b/prepare-sources/tsconfig.json @@ -3,11 +3,13 @@ "module": "nodenext", "types": ["node"], "noEmit": true, + "skipLibCheck": true, "allowImportingTsExtensions": true, "verbatimModuleSyntax": true, "erasableSyntaxOnly": true, "noUncheckedIndexedAccess": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true - } + }, + "exclude": ["**/__fixtures__/**"] } diff --git a/prepare-sources/vite.config.ts b/prepare-sources/vite.config.ts index db9ae56..835fe80 100644 --- a/prepare-sources/vite.config.ts +++ b/prepare-sources/vite.config.ts @@ -1,6 +1,9 @@ import { defineConfig } from "vite-plus"; export default defineConfig({ + fmt: { + ignorePatterns: ["**/__fixtures__/**"], + }, lint: { ignorePatterns: ["**/__fixtures__/**"], categories: {