isolate-package 1.32.0 → 1.33.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { c as detectPackageManager, i as defineConfig, l as readTypedJson, n as listInternalPackages, o as resolveConfig, r as createPackagesRegistry, s as resolveWorkspacePaths, t as isolate } from "./isolate-BRD2AgVJ.mjs";
1
+ import { c as detectPackageManager, i as defineConfig, l as readTypedJson, n as listInternalPackages, o as resolveConfig, r as createPackagesRegistry, s as resolveWorkspacePaths, t as isolate } from "./isolate-DTwgcMAN.mjs";
2
2
  import path from "node:path";
3
3
  //#region src/get-internal-package-names.ts
4
4
  /**
@@ -486,30 +486,8 @@ function resolveConfig(initialConfig) {
486
486
  return config;
487
487
  }
488
488
  //#endregion
489
- //#region src/lib/lockfile/helpers/generate-bun-lockfile.ts
490
- /**
491
- * Serialize a value to JSON with trailing commas after every array element and
492
- * object property, matching Bun's native bun.lock output format.
493
- */
494
- function serializeWithTrailingCommas(value, indent = 2) {
495
- /**
496
- * Add trailing commas after values that precede a closing bracket/brace.
497
- * Apply repeatedly because consecutive closing brackets (e.g. ]\n}) need
498
- * multiple passes — the first pass adds a comma after the inner value, and
499
- * subsequent passes handle the outer brackets.
500
- */
501
- let result = JSON.stringify(value, null, indent);
502
- let previous;
503
- do {
504
- previous = result;
505
- result = result.replace(/(["\d\w\]}-])\n(\s*[\]}])/g, "$1,\n$2");
506
- } while (result !== previous);
507
- return result;
508
- }
509
- /**
510
- * Extract dependency names from a workspace entry, optionally including
511
- * devDependencies.
512
- */
489
+ //#region src/lib/lockfile/helpers/bun-lockfile.ts
490
+ /** Extract dependency names from a workspace entry. */
513
491
  function collectDependencyNames(entry, includeDevDependencies) {
514
492
  const names = /* @__PURE__ */ new Set();
515
493
  for (const name of Object.keys(entry.dependencies ?? {})) names.add(name);
@@ -519,8 +497,8 @@ function collectDependencyNames(entry, includeDevDependencies) {
519
497
  return [...names];
520
498
  }
521
499
  /**
522
- * Check whether a package entry represents a workspace package by examining its
523
- * identifier string (first element in the entry array).
500
+ * Check whether a package entry represents a workspace package by examining
501
+ * its identifier string (first element in the entry array).
524
502
  */
525
503
  function isWorkspacePackageEntry(entry) {
526
504
  const ident = entry[0];
@@ -532,16 +510,16 @@ function isWorkspacePackageEntry(entry) {
532
510
  * - workspace packages: [ident, info] -> index 1
533
511
  * - git/github packages: [ident, info, checksum] -> index 1
534
512
  *
535
- * Detection: if the second element is a string (registry URL or checksum), the
536
- * info object is deeper. Workspace entries have only 2 elements.
513
+ * Detection: if the second element is a string (registry URL or checksum),
514
+ * the info object is deeper. Workspace entries have only 2 elements.
537
515
  */
538
516
  function getPackageInfoObject(entry) {
539
517
  if (entry.length <= 1) return void 0;
540
518
  /** Workspace entries: [ident, info] */
541
519
  if (isWorkspacePackageEntry(entry)) return typeof entry[1] === "object" ? entry[1] : void 0;
542
520
  /**
543
- * npm entries with registry URL: [ident, registryUrl, info, checksum].
544
- * The second element is a string (the registry URL).
521
+ * npm entries with registry URL: [ident, registryUrl, info, checksum]. The
522
+ * second element is a string (the registry URL).
545
523
  */
546
524
  if (typeof entry[1] === "string") return typeof entry[2] === "object" ? entry[2] : void 0;
547
525
  /** git/tarball entries: [ident, info, checksum] */
@@ -549,8 +527,8 @@ function getPackageInfoObject(entry) {
549
527
  }
550
528
  /**
551
529
  * Recursively collect all package keys that are required, starting from a set
552
- * of direct dependency names and walking through their transitive dependencies
553
- * in the packages section.
530
+ * of direct dependency names and walking through their transitive
531
+ * dependencies in the packages section.
554
532
  */
555
533
  function collectRequiredPackages(directDependencyNames, packages) {
556
534
  const required = /* @__PURE__ */ new Set();
@@ -577,6 +555,27 @@ function collectRequiredPackages(directDependencyNames, packages) {
577
555
  }
578
556
  return required;
579
557
  }
558
+ //#endregion
559
+ //#region src/lib/lockfile/helpers/generate-bun-lockfile.ts
560
+ /**
561
+ * Serialize a value to JSON with trailing commas after every array element and
562
+ * object property, matching Bun's native bun.lock output format.
563
+ */
564
+ function serializeWithTrailingCommas(value, indent = 2) {
565
+ /**
566
+ * Add trailing commas after values that precede a closing bracket/brace.
567
+ * Apply repeatedly because consecutive closing brackets (e.g. ]\n}) need
568
+ * multiple passes — the first pass adds a comma after the inner value, and
569
+ * subsequent passes handle the outer brackets.
570
+ */
571
+ let result = JSON.stringify(value, null, indent);
572
+ let previous;
573
+ do {
574
+ previous = result;
575
+ result = result.replace(/(["\d\w\]}-])\n(\s*[\]}])/g, "$1,\n$2");
576
+ } while (result !== previous);
577
+ return result;
578
+ }
580
579
  async function generateBunLockfile({ workspaceRootDir, targetPackageDir, isolateDir, internalDepPackageNames, packagesRegistry, includeDevDependencies }) {
581
580
  const log = useLogger();
582
581
  log.debug("Generating Bun lockfile...");
@@ -1553,10 +1552,252 @@ function listInternalPackages(manifest, packagesRegistry, { includeDevDependenci
1553
1552
  return [...new Set(result)];
1554
1553
  }
1555
1554
  //#endregion
1555
+ //#region src/lib/patches/collect-installed-names-bun.ts
1556
+ /**
1557
+ * Walk the workspace bun.lock starting from the target package and its
1558
+ * internal workspace dependencies, returning the set of every package name
1559
+ * that will end up installed in the isolate (including deep
1560
+ * external-to-external transitives).
1561
+ *
1562
+ * Used by `copyPatches` to preserve patches for transitive deps that aren't
1563
+ * directly listed on any internal manifest. Returns an empty set on any
1564
+ * failure so the caller falls back to manifest-based reachability.
1565
+ */
1566
+ function collectInstalledNamesFromBunLockfile({ workspaceRootDir, targetPackageDir, internalDepPackageNames, packagesRegistry, includeDevDependencies }) {
1567
+ const log = useLogger();
1568
+ try {
1569
+ const lockfilePath = path.join(workspaceRootDir, "bun.lock");
1570
+ if (!fs.existsSync(lockfilePath)) {
1571
+ log.debug("No bun.lock available for installed-names walk");
1572
+ return /* @__PURE__ */ new Set();
1573
+ }
1574
+ const lockfile = readTypedJsonSync(lockfilePath);
1575
+ const targetWorkspaceKey = path.relative(workspaceRootDir, targetPackageDir).split(path.sep).join(path.posix.sep);
1576
+ const internalWorkspaceKeys = internalDepPackageNames.map((name) => {
1577
+ const pkg = packagesRegistry[name];
1578
+ if (!pkg) return null;
1579
+ return pkg.rootRelativeDir.split(path.sep).join(path.posix.sep);
1580
+ }).filter((key) => Boolean(key));
1581
+ const directDependencyNames = /* @__PURE__ */ new Set();
1582
+ const targetEntry = lockfile.workspaces[targetWorkspaceKey];
1583
+ if (targetEntry) for (const name of collectDependencyNames(targetEntry, includeDevDependencies)) directDependencyNames.add(name);
1584
+ for (const workspaceKey of internalWorkspaceKeys) {
1585
+ const entry = lockfile.workspaces[workspaceKey];
1586
+ if (!entry) continue;
1587
+ /** Internal workspace deps never bring in their devDependencies */
1588
+ for (const name of collectDependencyNames(entry, false)) directDependencyNames.add(name);
1589
+ }
1590
+ return collectRequiredPackages(directDependencyNames, lockfile.packages);
1591
+ } catch (err) {
1592
+ log.debug(`Failed to walk bun.lock for installed names: ${err instanceof Error ? err.message : String(err)}`);
1593
+ return /* @__PURE__ */ new Set();
1594
+ }
1595
+ }
1596
+ //#endregion
1597
+ //#region src/lib/patches/collect-installed-names-pnpm.ts
1598
+ /**
1599
+ * Walk the workspace pnpm lockfile starting from the target package and its
1600
+ * internal workspace dependencies, returning the set of every package name
1601
+ * that will end up installed in the isolate (including deep
1602
+ * external-to-external transitives).
1603
+ *
1604
+ * Used by `copyPatches` to preserve patches for transitive deps that aren't
1605
+ * directly listed on any internal manifest. Returns an empty set on any
1606
+ * failure so the caller falls back to manifest-based reachability. When the
1607
+ * lockfile is present but lacks a `packages` section, returns just the
1608
+ * direct importer dep names.
1609
+ */
1610
+ async function collectInstalledNamesFromPnpmLockfile({ workspaceRootDir, targetPackageDir, internalDepPackageNames, packagesRegistry, majorVersion, includeDevDependencies }) {
1611
+ const log = useLogger();
1612
+ try {
1613
+ const useVersion9 = majorVersion >= 9;
1614
+ const isRush = isRushWorkspace(workspaceRootDir);
1615
+ const lockfileDir = isRush ? path.join(workspaceRootDir, "common/config/rush") : workspaceRootDir;
1616
+ const lockfile = useVersion9 ? await readWantedLockfile$1(lockfileDir, { ignoreIncompatible: false }) : await readWantedLockfile(lockfileDir, { ignoreIncompatible: false });
1617
+ if (!lockfile) {
1618
+ log.debug("No pnpm lockfile available for installed-names walk");
1619
+ return /* @__PURE__ */ new Set();
1620
+ }
1621
+ /**
1622
+ * Normalize separators to POSIX so Windows callers match the lockfile's
1623
+ * importer keys (mirrors generate-pnpm-lockfile.ts). Applied once here so
1624
+ * the `isTarget` equality check below compares apples-to-apples — without
1625
+ * this, on Windows the raw id with backslashes wouldn't match the
1626
+ * normalized id used as the importers map key.
1627
+ */
1628
+ const targetImporterId = toLockfileImporterKey(useVersion9 ? getLockfileImporterId$1(workspaceRootDir, targetPackageDir) : getLockfileImporterId(workspaceRootDir, targetPackageDir), isRush);
1629
+ const importerIds = [targetImporterId, ...internalDepPackageNames.map((name) => packagesRegistry[name]?.rootRelativeDir).filter((dir) => Boolean(dir)).map((dir) => toLockfileImporterKey(dir, isRush))];
1630
+ const packages = lockfile.packages;
1631
+ if (!packages) {
1632
+ log.debug("Lockfile has no packages section to walk");
1633
+ return collectImporterDirectNames(lockfile.importers, importerIds, targetImporterId, includeDevDependencies);
1634
+ }
1635
+ const names = /* @__PURE__ */ new Set();
1636
+ const seen = /* @__PURE__ */ new Set();
1637
+ const queue = [];
1638
+ for (const importerId of importerIds) {
1639
+ const importer = lockfile.importers[importerId];
1640
+ if (!importer) continue;
1641
+ enqueueImporterDeps({
1642
+ importer,
1643
+ names,
1644
+ queue,
1645
+ useVersion9,
1646
+ includeDevDependencies: importerId === targetImporterId && includeDevDependencies
1647
+ });
1648
+ }
1649
+ while (queue.length > 0) {
1650
+ const depPath = queue.pop();
1651
+ if (seen.has(depPath)) continue;
1652
+ seen.add(depPath);
1653
+ names.add(extractPackageName(depPath));
1654
+ const pkg = packages[depPath];
1655
+ if (!pkg) continue;
1656
+ enqueueResolvedDeps(pkg.dependencies, names, queue, useVersion9, seen);
1657
+ enqueueResolvedDeps(pkg.optionalDependencies, names, queue, useVersion9, seen);
1658
+ /**
1659
+ * Peer requirement values are name → semver-range, not resolved depPaths.
1660
+ * Just record the names so a patch on a peer-only external transitive
1661
+ * survives filtering (mirrors the bun walker and the sister manifest
1662
+ * walker, which both include peerDependencies).
1663
+ */
1664
+ collectNames(pkg.peerDependencies, names);
1665
+ }
1666
+ return names;
1667
+ } catch (err) {
1668
+ log.debug(`Failed to walk pnpm lockfile for installed names: ${err instanceof Error ? err.message : String(err)}`);
1669
+ return /* @__PURE__ */ new Set();
1670
+ }
1671
+ }
1672
+ /**
1673
+ * Convert a raw importer id (as returned by `getLockfileImporterId` or a
1674
+ * package's rootRelativeDir) to the form actually used as a key in
1675
+ * `lockfile.importers`: POSIX separators, with the Rush `../../` prefix when
1676
+ * the workspace lives under `common/config/rush`. Lockfile keys are always
1677
+ * POSIX regardless of the host OS, so backslashes are normalized
1678
+ * unconditionally rather than relying on `path.sep`.
1679
+ */
1680
+ function toLockfileImporterKey(importerId, isRush) {
1681
+ const posix = importerId.split(path.sep).join(path.posix.sep).replace(/\\/g, "/");
1682
+ return isRush ? `../../${posix}` : posix;
1683
+ }
1684
+ function enqueueImporterDeps({ importer, names, queue, useVersion9, includeDevDependencies }) {
1685
+ enqueueResolvedDeps(importer.dependencies, names, queue, useVersion9);
1686
+ enqueueResolvedDeps(importer.optionalDependencies, names, queue, useVersion9);
1687
+ if (includeDevDependencies) enqueueResolvedDeps(importer.devDependencies, names, queue, useVersion9);
1688
+ /**
1689
+ * Importer peerDependencies usually aren't a separate map in the lockfile
1690
+ * (autoInstallPeers folds them into `dependencies`), but record names if
1691
+ * they happen to be present.
1692
+ */
1693
+ collectNames(importer.peerDependencies, names);
1694
+ }
1695
+ function enqueueResolvedDeps(deps, names, queue, useVersion9, seen) {
1696
+ if (!deps) return;
1697
+ for (const [alias, ref] of Object.entries(deps)) {
1698
+ /**
1699
+ * The alias is the name as listed in the parent's dependencies map. For
1700
+ * non-aliased installs this is also the resolved package name. We add it
1701
+ * to the set as a candidate name; visiting the actual depPath below
1702
+ * refines this with the true installed name.
1703
+ */
1704
+ names.add(alias);
1705
+ const depPath = refToRelative(ref, alias, useVersion9);
1706
+ if (depPath && !seen?.has(depPath)) queue.push(depPath);
1707
+ }
1708
+ }
1709
+ function collectNames(deps, names) {
1710
+ if (!deps) return;
1711
+ for (const name of Object.keys(deps)) names.add(name);
1712
+ }
1713
+ /**
1714
+ * Mirrors `@pnpm/dependency-path`'s `refToRelative`. The depPath shape differs
1715
+ * between pnpm 8 (lockfile v6, normalized to v5 keys like `/foo/1.0.0`) and
1716
+ * pnpm 9 (lockfile v9 keys like `foo@1.0.0`). Returns the depPath used as a
1717
+ * key in `lockfile.packages`, or null if the ref points to a workspace link.
1718
+ */
1719
+ function refToRelative(reference, pkgName, useVersion9) {
1720
+ if (!reference) return null;
1721
+ if (reference.startsWith("link:")) return null;
1722
+ return useVersion9 ? refToRelativeV9(reference, pkgName) : refToRelativeV8(reference, pkgName);
1723
+ }
1724
+ function refToRelativeV9(reference, pkgName) {
1725
+ if (reference.startsWith("@")) return reference;
1726
+ const atIndex = reference.indexOf("@");
1727
+ if (atIndex === -1) return `${pkgName}@${reference}`;
1728
+ const colonIndex = reference.indexOf(":");
1729
+ const bracketIndex = reference.indexOf("(");
1730
+ if ((colonIndex === -1 || atIndex < colonIndex) && (bracketIndex === -1 || atIndex < bracketIndex)) return reference;
1731
+ return `${pkgName}@${reference}`;
1732
+ }
1733
+ /**
1734
+ * v8 form: pnpm 8 (lockfile v6) is normalized on read to v5-style depPaths
1735
+ * with leading slash and `/` separator between name and version. Plain
1736
+ * version refs build that key; refs already containing a `/` (peer-suffixed
1737
+ * or pre-formed) are returned verbatim. Mirrors `@pnpm/dependency-path@2.x`.
1738
+ */
1739
+ function refToRelativeV8(reference, pkgName) {
1740
+ if (reference.startsWith("file:")) return reference;
1741
+ const slashIndex = reference.indexOf("/");
1742
+ const bracketIndex = reference.indexOf("(");
1743
+ const noSlashBeforeBracket = bracketIndex !== -1 && reference.lastIndexOf("/", bracketIndex) === -1;
1744
+ if (slashIndex === -1 || noSlashBeforeBracket) return `/${pkgName}/${reference}`;
1745
+ return reference;
1746
+ }
1747
+ /**
1748
+ * Extract the bare package name from a pnpm depPath. Strips the optional
1749
+ * peer-resolution suffix (e.g. `(react@18.0.0)`) before parsing. Handles
1750
+ * both v9 (`@scope/foo@1.0.0`) and v8 (`/@scope/foo/1.0.0`) shapes.
1751
+ */
1752
+ function extractPackageName(depPath) {
1753
+ const peerStart = indexOfPeersSuffix(depPath);
1754
+ const trimmed = peerStart === -1 ? depPath : depPath.substring(0, peerStart);
1755
+ if (trimmed.startsWith("/")) {
1756
+ /** v8 v5-style: `/<name>/<version>` */
1757
+ const stripped = trimmed.slice(1);
1758
+ if (stripped.startsWith("@")) {
1759
+ const secondSlash = stripped.indexOf("/", stripped.indexOf("/") + 1);
1760
+ return secondSlash === -1 ? stripped : stripped.slice(0, secondSlash);
1761
+ }
1762
+ const firstSlash = stripped.indexOf("/");
1763
+ return firstSlash === -1 ? stripped : stripped.slice(0, firstSlash);
1764
+ }
1765
+ return getPackageName(trimmed);
1766
+ }
1767
+ /**
1768
+ * Mirrors `@pnpm/dependency-path`'s `indexOfPeersSuffix`. Returns the index
1769
+ * where the peer-resolution suffix starts, or -1 if there is none.
1770
+ */
1771
+ function indexOfPeersSuffix(depPath) {
1772
+ if (!depPath.endsWith(")")) return -1;
1773
+ let open = 1;
1774
+ for (let i = depPath.length - 2; i >= 0; i--) if (depPath[i] === "(") open--;
1775
+ else if (depPath[i] === ")") open++;
1776
+ else if (!open) return i + 1;
1777
+ return -1;
1778
+ }
1779
+ /**
1780
+ * Fallback when the lockfile is missing `packages`: just return importer
1781
+ * direct dep names so we at least cover some of the graph.
1782
+ */
1783
+ function collectImporterDirectNames(importers, importerIds, targetImporterId, includeDevDependencies) {
1784
+ const names = /* @__PURE__ */ new Set();
1785
+ for (const importerId of importerIds) {
1786
+ const importer = importers[importerId];
1787
+ if (!importer) continue;
1788
+ const isTarget = importerId === targetImporterId;
1789
+ for (const name of Object.keys(importer.dependencies ?? {})) names.add(name);
1790
+ for (const name of Object.keys(importer.optionalDependencies ?? {})) names.add(name);
1791
+ for (const name of Object.keys(importer.peerDependencies ?? {})) names.add(name);
1792
+ if (isTarget && includeDevDependencies) for (const name of Object.keys(importer.devDependencies ?? {})) names.add(name);
1793
+ }
1794
+ return names;
1795
+ }
1796
+ //#endregion
1556
1797
  //#region src/lib/patches/copy-patches.ts
1557
- async function copyPatches({ workspaceRootDir, targetPackageManifest, packagesRegistry, isolateDir, includeDevDependencies }) {
1798
+ async function copyPatches({ workspaceRootDir, targetPackageDir, targetPackageManifest, packagesRegistry, internalDepPackageNames, isolateDir, includeDevDependencies }) {
1558
1799
  const log = useLogger();
1559
- const { name: packageManagerName } = usePackageManager();
1800
+ const { name: packageManagerName, majorVersion } = usePackageManager();
1560
1801
  let patchedDependencies;
1561
1802
  /**
1562
1803
  * Only try reading pnpm-workspace.yaml for pnpm workspaces. Bun workspaces
@@ -1594,6 +1835,28 @@ async function copyPatches({ workspaceRootDir, targetPackageManifest, packagesRe
1594
1835
  packagesRegistry,
1595
1836
  includeDevDependencies
1596
1837
  });
1838
+ /**
1839
+ * Manifest-based reachability misses external→external transitives because
1840
+ * external manifests aren't loaded here. Walk the package-manager's
1841
+ * lockfile to also pick up those names, so a patch for a deeply-nested
1842
+ * external dep (e.g. `@react-pdf/render` reached via `@react-pdf/renderer`)
1843
+ * survives isolation.
1844
+ */
1845
+ const lockfileInstalledNames = packageManagerName === "pnpm" ? await collectInstalledNamesFromPnpmLockfile({
1846
+ workspaceRootDir,
1847
+ targetPackageDir,
1848
+ internalDepPackageNames,
1849
+ packagesRegistry,
1850
+ majorVersion,
1851
+ includeDevDependencies
1852
+ }) : packageManagerName === "bun" ? collectInstalledNamesFromBunLockfile({
1853
+ workspaceRootDir,
1854
+ targetPackageDir,
1855
+ internalDepPackageNames,
1856
+ packagesRegistry,
1857
+ includeDevDependencies
1858
+ }) : /* @__PURE__ */ new Set();
1859
+ for (const name of lockfileInstalledNames) reachableDependencyNames.add(name);
1597
1860
  const filteredPatches = filterPatchedDependencies({
1598
1861
  patchedDependencies,
1599
1862
  targetPackageManifest,
@@ -1644,6 +1907,58 @@ async function readLockfilePatchedDependencies(workspaceRootDir) {
1644
1907
  }
1645
1908
  }
1646
1909
  //#endregion
1910
+ //#region src/lib/patches/write-isolate-pnpm-workspace.ts
1911
+ /**
1912
+ * Copy `pnpm-workspace.yaml` from the workspace root to the isolate directory,
1913
+ * filtering its `patchedDependencies` field so it only references patches that
1914
+ * were actually copied to the isolate. Without this, `pnpm install` in the
1915
+ * isolate fails when patches that don't apply to the target package are
1916
+ * declared in the workspace root config (see issue #178).
1917
+ *
1918
+ * The yaml is only rewritten when filtering is required. The file is copied
1919
+ * verbatim — preserving comments, key order, and trailing whitespace — when
1920
+ * any of the following hold:
1921
+ *
1922
+ * - The source yaml cannot be read or parsed.
1923
+ * - The parsed settings have no `patchedDependencies` field.
1924
+ * - Every entry in `patchedDependencies` is also present in `copiedPatches`
1925
+ * (no exclusions, so rewriting would only churn formatting).
1926
+ *
1927
+ * Otherwise, `patchedDependencies` is rewritten to the entries in
1928
+ * `copiedPatches` (or removed entirely when none remain).
1929
+ */
1930
+ function writeIsolatePnpmWorkspace({ workspaceRootDir, isolateDir, copiedPatches }) {
1931
+ const log = useLogger();
1932
+ const sourcePath = path.join(workspaceRootDir, "pnpm-workspace.yaml");
1933
+ const targetPath = path.join(isolateDir, "pnpm-workspace.yaml");
1934
+ let settings;
1935
+ try {
1936
+ settings = readTypedYamlSync(sourcePath);
1937
+ } catch (error) {
1938
+ log.warn(`Could not read pnpm-workspace.yaml, falling back to verbatim copy: ${error instanceof Error ? error.message : String(error)}`);
1939
+ fs.copyFileSync(sourcePath, targetPath);
1940
+ return;
1941
+ }
1942
+ if (!settings || !settings.patchedDependencies) {
1943
+ fs.copyFileSync(sourcePath, targetPath);
1944
+ return;
1945
+ }
1946
+ /**
1947
+ * If every patch declared in the source yaml was kept, copy verbatim so
1948
+ * comments, ordering, and trailing whitespace are preserved.
1949
+ */
1950
+ const sourceSpecs = Object.keys(settings.patchedDependencies);
1951
+ const copiedSpecs = new Set(Object.keys(copiedPatches));
1952
+ if (!sourceSpecs.some((spec) => !copiedSpecs.has(spec))) {
1953
+ fs.copyFileSync(sourcePath, targetPath);
1954
+ return;
1955
+ }
1956
+ const filteredEntries = Object.entries(copiedPatches).map(([spec, patchFile]) => [spec, patchFile.path]);
1957
+ if (filteredEntries.length > 0) settings.patchedDependencies = Object.fromEntries(filteredEntries);
1958
+ else delete settings.patchedDependencies;
1959
+ writeTypedYamlSync(targetPath, settings);
1960
+ }
1961
+ //#endregion
1647
1962
  //#region src/isolate.ts
1648
1963
  const __dirname = getDirname(import.meta.url);
1649
1964
  function createIsolator(config) {
@@ -1742,8 +2057,10 @@ function createIsolator(config) {
1742
2057
  await writeManifest(isolateDir, outputManifest);
1743
2058
  const copiedPatches = (packageManager.name === "pnpm" || packageManager.name === "bun") && !config.forceNpm ? await copyPatches({
1744
2059
  workspaceRootDir,
2060
+ targetPackageDir,
1745
2061
  targetPackageManifest: outputManifest,
1746
2062
  packagesRegistry,
2063
+ internalDepPackageNames: internalPackageNames,
1747
2064
  isolateDir,
1748
2065
  includeDevDependencies: config.includeDevDependencies
1749
2066
  }) : {};
@@ -1794,7 +2111,11 @@ function createIsolator(config) {
1794
2111
  log.debug("Packages folder names:", packagesFolderNames);
1795
2112
  const packages = packagesFolderNames.map((x) => path.join(x, "/*"));
1796
2113
  writeTypedYamlSync(path.join(isolateDir, "pnpm-workspace.yaml"), { packages });
1797
- } else fs.copyFileSync(path.join(workspaceRootDir, "pnpm-workspace.yaml"), path.join(isolateDir, "pnpm-workspace.yaml"));
2114
+ } else writeIsolatePnpmWorkspace({
2115
+ workspaceRootDir,
2116
+ isolateDir,
2117
+ copiedPatches
2118
+ });
1798
2119
  if (packageManager.name === "bun" && !config.forceNpm) {
1799
2120
  /** Add workspaces field to the manifest so Bun treats the isolate as a workspace */
1800
2121
  const manifest = await readManifest(isolateDir);
@@ -1837,4 +2158,4 @@ async function isolate(config) {
1837
2158
  //#endregion
1838
2159
  export { loadConfigFromFile as a, detectPackageManager as c, defineConfig as i, readTypedJson as l, listInternalPackages as n, resolveConfig as o, createPackagesRegistry as r, resolveWorkspacePaths as s, isolate as t, filterObjectUndefined as u };
1839
2160
 
1840
- //# sourceMappingURL=isolate-BRD2AgVJ.mjs.map
2161
+ //# sourceMappingURL=isolate-DTwgcMAN.mjs.map