@antongolub/lockfile 0.0.0-snapshot.47 → 0.0.0-snapshot.48

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.
@@ -1349,7 +1349,7 @@ function stringifyFamily(graph, config, options = {}) {
1349
1349
  const rootMeta = sidecar?.rootMeta;
1350
1350
  const rootName = rootMeta?.name ?? rootNode?.name ?? "";
1351
1351
  const rootVersion = rootMeta?.version ?? rootNode?.version ?? "0.0.0";
1352
- const plannedInstallPaths = deriveInstallPathsForStringify(graph, sidecar, rootNode);
1352
+ const plannedInstallPaths = deriveInstallPathsForStringify(graph, sidecar, rootNode, emitDiagnostic);
1353
1353
  const packages = {};
1354
1354
  if (rootNode !== void 0) {
1355
1355
  packages[""] = buildRootEntry(graph, rootNode, rootMeta, sidecar, emitDiagnostic);
@@ -1710,7 +1710,7 @@ function locateRootNode(graph, sidecar) {
1710
1710
  }
1711
1711
  return void 0;
1712
1712
  }
1713
- function deriveInstallPathsForStringify(graph, sidecar, rootNode) {
1713
+ function deriveInstallPathsForStringify(graph, sidecar, rootNode, onDiagnostic) {
1714
1714
  const byNodeId = /* @__PURE__ */ new Map();
1715
1715
  const pathToId = /* @__PURE__ */ new Map();
1716
1716
  const seenConsumers = /* @__PURE__ */ new Set();
@@ -1769,11 +1769,19 @@ function deriveInstallPathsForStringify(graph, sidecar, rootNode) {
1769
1769
  }
1770
1770
  }
1771
1771
  };
1772
- drainBfsQueue();
1773
- for (const node of seededNodes) {
1774
- if (byNodeId.has(node.id)) continue;
1775
- addPlacement(node.id, fallbackInstallPathForNode(node, pathToId));
1772
+ const captureComplete = seededNodes.length > 0 && seededNodes.every((node) => (sidecar?.nodes.get(node.id)?.installPaths?.length ?? 0) > 0);
1773
+ if (!captureComplete) {
1776
1774
  drainBfsQueue();
1775
+ for (const node of seededNodes) {
1776
+ if (byNodeId.has(node.id)) continue;
1777
+ addPlacement(node.id, fallbackInstallPathForNode(node, pathToId));
1778
+ drainBfsQueue();
1779
+ }
1780
+ onDiagnostic?.({
1781
+ code: "LAYOUT_PLACEMENT_RESYNTHESISED",
1782
+ severity: "info",
1783
+ message: "npm install-path layout re-synthesised \u2014 no complete parse-captured placement (cross-PM input or post-mutate graph); emitted a valid find-up tree, not the original projection"
1784
+ });
1777
1785
  }
1778
1786
  const planned = /* @__PURE__ */ new Map();
1779
1787
  for (const [nodeId, installPaths] of byNodeId) {
@@ -1349,7 +1349,7 @@ function stringifyFamily(graph, config, options = {}) {
1349
1349
  const rootMeta = sidecar?.rootMeta;
1350
1350
  const rootName = rootMeta?.name ?? rootNode?.name ?? "";
1351
1351
  const rootVersion = rootMeta?.version ?? rootNode?.version ?? "0.0.0";
1352
- const plannedInstallPaths = deriveInstallPathsForStringify(graph, sidecar, rootNode);
1352
+ const plannedInstallPaths = deriveInstallPathsForStringify(graph, sidecar, rootNode, emitDiagnostic);
1353
1353
  const packages = {};
1354
1354
  if (rootNode !== void 0) {
1355
1355
  packages[""] = buildRootEntry(graph, rootNode, rootMeta, sidecar, emitDiagnostic);
@@ -1710,7 +1710,7 @@ function locateRootNode(graph, sidecar) {
1710
1710
  }
1711
1711
  return void 0;
1712
1712
  }
1713
- function deriveInstallPathsForStringify(graph, sidecar, rootNode) {
1713
+ function deriveInstallPathsForStringify(graph, sidecar, rootNode, onDiagnostic) {
1714
1714
  const byNodeId = /* @__PURE__ */ new Map();
1715
1715
  const pathToId = /* @__PURE__ */ new Map();
1716
1716
  const seenConsumers = /* @__PURE__ */ new Set();
@@ -1769,11 +1769,19 @@ function deriveInstallPathsForStringify(graph, sidecar, rootNode) {
1769
1769
  }
1770
1770
  }
1771
1771
  };
1772
- drainBfsQueue();
1773
- for (const node of seededNodes) {
1774
- if (byNodeId.has(node.id)) continue;
1775
- addPlacement(node.id, fallbackInstallPathForNode(node, pathToId));
1772
+ const captureComplete = seededNodes.length > 0 && seededNodes.every((node) => (sidecar?.nodes.get(node.id)?.installPaths?.length ?? 0) > 0);
1773
+ if (!captureComplete) {
1776
1774
  drainBfsQueue();
1775
+ for (const node of seededNodes) {
1776
+ if (byNodeId.has(node.id)) continue;
1777
+ addPlacement(node.id, fallbackInstallPathForNode(node, pathToId));
1778
+ drainBfsQueue();
1779
+ }
1780
+ onDiagnostic?.({
1781
+ code: "LAYOUT_PLACEMENT_RESYNTHESISED",
1782
+ severity: "info",
1783
+ message: "npm install-path layout re-synthesised \u2014 no complete parse-captured placement (cross-PM input or post-mutate graph); emitted a valid find-up tree, not the original projection"
1784
+ });
1777
1785
  }
1778
1786
  const planned = /* @__PURE__ */ new Map();
1779
1787
  for (const [nodeId, installPaths] of byNodeId) {
@@ -2292,8 +2292,16 @@ function resolvePeerTargetById(seenIds, peerName, peerVersion) {
2292
2292
  return void 0;
2293
2293
  }
2294
2294
  function resolveWorkspacePeerId(peerVersion, importerByPath) {
2295
- const importerPath = peerVersion.replace(/\+/g, "/");
2296
- return importerByPath.get(importerPath);
2295
+ let path2 = peerVersion.replace(/\+/g, "/");
2296
+ const exact = importerByPath.get(path2);
2297
+ if (exact !== void 0) return exact;
2298
+ while (path2.includes("/")) {
2299
+ path2 = path2.slice(0, path2.lastIndexOf("/"));
2300
+ if (path2.length === 0 || path2 === ".") break;
2301
+ const ancestor = importerByPath.get(path2);
2302
+ if (ancestor !== void 0) return ancestor;
2303
+ }
2304
+ return void 0;
2297
2305
  }
2298
2306
  function buildPeerContext(peers, importerByPath) {
2299
2307
  return peers.filter((p) => resolveWorkspacePeerId(p.version, importerByPath) === void 0).map((p) => `${p.name}@${p.version}`).sort();
@@ -2292,8 +2292,16 @@ function resolvePeerTargetById(seenIds, peerName, peerVersion) {
2292
2292
  return void 0;
2293
2293
  }
2294
2294
  function resolveWorkspacePeerId(peerVersion, importerByPath) {
2295
- const importerPath = peerVersion.replace(/\+/g, "/");
2296
- return importerByPath.get(importerPath);
2295
+ let path2 = peerVersion.replace(/\+/g, "/");
2296
+ const exact = importerByPath.get(path2);
2297
+ if (exact !== void 0) return exact;
2298
+ while (path2.includes("/")) {
2299
+ path2 = path2.slice(0, path2.lastIndexOf("/"));
2300
+ if (path2.length === 0 || path2 === ".") break;
2301
+ const ancestor = importerByPath.get(path2);
2302
+ if (ancestor !== void 0) return ancestor;
2303
+ }
2304
+ return void 0;
2297
2305
  }
2298
2306
  function buildPeerContext(peers, importerByPath) {
2299
2307
  return peers.filter((p) => resolveWorkspacePeerId(p.version, importerByPath) === void 0).map((p) => `${p.name}@${p.version}`).sort();
@@ -934,16 +934,22 @@ var HEADER = "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n
934
934
  var HEADER_LINE_1 = "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.";
935
935
  var HEADER_LINE_2 = "# yarn lockfile v1";
936
936
  var cmpUtf16 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
937
- var QUOTED_PAIR_RE = /^("(?:\\.|[^"])*"|[^\s"].*) "(?:\\.|[^"])*"$/;
937
+ var DEP_PAIR_RE = /^("(?:\\.|[^"])*"|[^\s"]\S*) ("(?:\\.|[^"])*"|[^\s"]\S*)$/;
938
938
  var BARE_DEP_NAME_RE = /^[A-Za-z0-9._-]+$/;
939
939
  var ENTRY_KEY_SPECIAL_RE = /[\s:",#?*&!|>'`[\]{}]/;
940
940
  var BERRY_HEADER_RE = /^__metadata:\s*(?:\r?\n|$)/m;
941
941
  var sidecarByGraph = /* @__PURE__ */ new WeakMap();
942
+ function stripBom(input) {
943
+ return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
944
+ }
942
945
  function check(input) {
943
- return normalizeLineEndings(input).startsWith(HEADER);
946
+ const normalized = stripBom(normalizeLineEndings(input));
947
+ if (normalized.startsWith(HEADER)) return true;
948
+ const lines = normalized.split("\n");
949
+ return lines[0] === HEADER_LINE_1 && lines[1] === HEADER_LINE_2;
944
950
  }
945
951
  function parse2(input) {
946
- const normalized = normalizeLineEndings(input);
952
+ const normalized = stripBom(normalizeLineEndings(input));
947
953
  ensureClassicHeader(normalized);
948
954
  const builder = newBuilder();
949
955
  const diagnostics = [];
@@ -1321,7 +1327,7 @@ function splitMixedDescriptorList(token) {
1321
1327
  }
1322
1328
  function parseDependencyLine(line) {
1323
1329
  const raw = line.slice(4);
1324
- if (!QUOTED_PAIR_RE.test(raw)) {
1330
+ if (!DEP_PAIR_RE.test(raw)) {
1325
1331
  throw parseFailed(`malformed dependency line (${JSON.stringify(line)})`);
1326
1332
  }
1327
1333
  const splitAt = splitDependencyPair(raw);
@@ -1329,7 +1335,7 @@ function parseDependencyLine(line) {
1329
1335
  const rangeToken = raw.slice(splitAt + 1);
1330
1336
  return [
1331
1337
  nameToken.startsWith('"') ? parseQuotedToken(nameToken) : nameToken,
1332
- parseQuotedToken(rangeToken)
1338
+ rangeToken.startsWith('"') ? parseQuotedToken(rangeToken) : rangeToken
1333
1339
  ];
1334
1340
  }
1335
1341
  function splitDependencyPair(raw) {
package/dist/index.js CHANGED
@@ -1579,7 +1579,7 @@ function stringifyFamily(graph, config, options = {}) {
1579
1579
  const rootMeta = sidecar?.rootMeta;
1580
1580
  const rootName = rootMeta?.name ?? rootNode?.name ?? "";
1581
1581
  const rootVersion = rootMeta?.version ?? rootNode?.version ?? "0.0.0";
1582
- const plannedInstallPaths = deriveInstallPathsForStringify(graph, sidecar, rootNode);
1582
+ const plannedInstallPaths = deriveInstallPathsForStringify(graph, sidecar, rootNode, emitDiagnostic);
1583
1583
  const packages = {};
1584
1584
  if (rootNode !== void 0) {
1585
1585
  packages[""] = buildRootEntry(graph, rootNode, rootMeta, sidecar, emitDiagnostic);
@@ -1789,7 +1789,7 @@ function locateRootNode(graph, sidecar) {
1789
1789
  }
1790
1790
  return void 0;
1791
1791
  }
1792
- function deriveInstallPathsForStringify(graph, sidecar, rootNode) {
1792
+ function deriveInstallPathsForStringify(graph, sidecar, rootNode, onDiagnostic) {
1793
1793
  const byNodeId = /* @__PURE__ */ new Map();
1794
1794
  const pathToId = /* @__PURE__ */ new Map();
1795
1795
  const seenConsumers = /* @__PURE__ */ new Set();
@@ -1848,11 +1848,19 @@ function deriveInstallPathsForStringify(graph, sidecar, rootNode) {
1848
1848
  }
1849
1849
  }
1850
1850
  };
1851
- drainBfsQueue();
1852
- for (const node of seededNodes) {
1853
- if (byNodeId.has(node.id)) continue;
1854
- addPlacement(node.id, fallbackInstallPathForNode(node, pathToId));
1851
+ const captureComplete = seededNodes.length > 0 && seededNodes.every((node) => (sidecar?.nodes.get(node.id)?.installPaths?.length ?? 0) > 0);
1852
+ if (!captureComplete) {
1855
1853
  drainBfsQueue();
1854
+ for (const node of seededNodes) {
1855
+ if (byNodeId.has(node.id)) continue;
1856
+ addPlacement(node.id, fallbackInstallPathForNode(node, pathToId));
1857
+ drainBfsQueue();
1858
+ }
1859
+ onDiagnostic?.({
1860
+ code: "LAYOUT_PLACEMENT_RESYNTHESISED",
1861
+ severity: "info",
1862
+ message: "npm install-path layout re-synthesised \u2014 no complete parse-captured placement (cross-PM input or post-mutate graph); emitted a valid find-up tree, not the original projection"
1863
+ });
1856
1864
  }
1857
1865
  const planned = /* @__PURE__ */ new Map();
1858
1866
  for (const [nodeId, installPaths] of byNodeId) {
@@ -3313,8 +3321,16 @@ function resolvePeerTargetById(seenIds, peerName, peerVersion) {
3313
3321
  return void 0;
3314
3322
  }
3315
3323
  function resolveWorkspacePeerId(peerVersion, importerByPath) {
3316
- const importerPath = peerVersion.replace(/\+/g, "/");
3317
- return importerByPath.get(importerPath);
3324
+ let path6 = peerVersion.replace(/\+/g, "/");
3325
+ const exact = importerByPath.get(path6);
3326
+ if (exact !== void 0) return exact;
3327
+ while (path6.includes("/")) {
3328
+ path6 = path6.slice(0, path6.lastIndexOf("/"));
3329
+ if (path6.length === 0 || path6 === ".") break;
3330
+ const ancestor = importerByPath.get(path6);
3331
+ if (ancestor !== void 0) return ancestor;
3332
+ }
3333
+ return void 0;
3318
3334
  }
3319
3335
  function buildPeerContext(peers, importerByPath) {
3320
3336
  return peers.filter((p) => resolveWorkspacePeerId(p.version, importerByPath) === void 0).map((p) => `${p.name}@${p.version}`).sort();
@@ -6811,16 +6827,22 @@ var HEADER = "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n
6811
6827
  var HEADER_LINE_1 = "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.";
6812
6828
  var HEADER_LINE_2 = "# yarn lockfile v1";
6813
6829
  var cmpUtf16 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
6814
- var QUOTED_PAIR_RE = /^("(?:\\.|[^"])*"|[^\s"].*) "(?:\\.|[^"])*"$/;
6830
+ var DEP_PAIR_RE = /^("(?:\\.|[^"])*"|[^\s"]\S*) ("(?:\\.|[^"])*"|[^\s"]\S*)$/;
6815
6831
  var BARE_DEP_NAME_RE = /^[A-Za-z0-9._-]+$/;
6816
6832
  var ENTRY_KEY_SPECIAL_RE = /[\s:",#?*&!|>'`[\]{}]/;
6817
6833
  var BERRY_HEADER_RE = /^__metadata:\s*(?:\r?\n|$)/m;
6818
6834
  var sidecarByGraph7 = /* @__PURE__ */ new WeakMap();
6835
+ function stripBom(input) {
6836
+ return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
6837
+ }
6819
6838
  function check15(input) {
6820
- return normalizeLineEndings3(input).startsWith(HEADER);
6839
+ const normalized = stripBom(normalizeLineEndings3(input));
6840
+ if (normalized.startsWith(HEADER)) return true;
6841
+ const lines = normalized.split("\n");
6842
+ return lines[0] === HEADER_LINE_1 && lines[1] === HEADER_LINE_2;
6821
6843
  }
6822
6844
  function parse17(input) {
6823
- const normalized = normalizeLineEndings3(input);
6845
+ const normalized = stripBom(normalizeLineEndings3(input));
6824
6846
  ensureClassicHeader(normalized);
6825
6847
  const builder = newBuilder();
6826
6848
  const diagnostics = [];
@@ -7100,7 +7122,7 @@ function splitMixedDescriptorList(token) {
7100
7122
  }
7101
7123
  function parseDependencyLine(line) {
7102
7124
  const raw = line.slice(4);
7103
- if (!QUOTED_PAIR_RE.test(raw)) {
7125
+ if (!DEP_PAIR_RE.test(raw)) {
7104
7126
  throw parseFailed2(`malformed dependency line (${JSON.stringify(line)})`);
7105
7127
  }
7106
7128
  const splitAt = splitDependencyPair(raw);
@@ -7108,7 +7130,7 @@ function parseDependencyLine(line) {
7108
7130
  const rangeToken = raw.slice(splitAt + 1);
7109
7131
  return [
7110
7132
  nameToken.startsWith('"') ? parseQuotedToken(nameToken) : nameToken,
7111
- parseQuotedToken(rangeToken)
7133
+ rangeToken.startsWith('"') ? parseQuotedToken(rangeToken) : rangeToken
7112
7134
  ];
7113
7135
  }
7114
7136
  function splitDependencyPair(raw) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antongolub/lockfile",
3
- "version": "0.0.0-snapshot.47",
3
+ "version": "0.0.0-snapshot.48",
4
4
  "private": false,
5
5
  "description": "Universal lockfile model and converter for npm, yarn, pnpm, bun",
6
6
  "type": "module",