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

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.
@@ -12,12 +12,17 @@ var LockfileError = class extends Error {
12
12
  };
13
13
  var CANONICAL_HASH_RE = /^[0-9a-f]{128}$/;
14
14
  var SENTINEL_RE = /^unresolved-[0-9a-f]{64}$/;
15
+ var HASHED_PEER_SET_RE = /^[0-9a-f]{16,}$/;
15
16
  function isCanonicalHash(s) {
16
17
  return CANONICAL_HASH_RE.test(s);
17
18
  }
18
19
  function isSentinelPatch(s) {
19
20
  return SENTINEL_RE.test(s);
20
21
  }
22
+ function isHashedPeerSetToken(seg) {
23
+ if (seg.startsWith("patch_hash=")) return false;
24
+ return HASHED_PEER_SET_RE.test(seg);
25
+ }
21
26
 
22
27
  // src/main/ts/graph.ts
23
28
  var GraphError = class extends Error {
@@ -226,7 +231,7 @@ function validate(s) {
226
231
  throw new GraphError("INVARIANT_VIOLATION", `node id ${id} disagrees with derived id ${expected.join(" or ")}`);
227
232
  }
228
233
  const peerEdgeTargets = (s.outgoing.get(id) ?? []).filter((e) => e.kind === "peer").map((e) => stripPeerContextFromNodeId(e.dst)).sort();
229
- const peerCtx = node.peerContext.map(stripPeerContextFromNodeId).sort();
234
+ const peerCtx = node.peerContext.filter((p) => !isHashedPeerSetToken(stripPeerContextFromNodeId(p))).map(stripPeerContextFromNodeId).sort();
230
235
  if (peerEdgeTargets.length !== peerCtx.length || peerEdgeTargets.some((t, i) => t !== peerCtx[i])) {
231
236
  throw new GraphError("INVARIANT_VIOLATION", `peer edges of ${id} disagree with peerContext`);
232
237
  }
@@ -13,12 +13,17 @@ var LockfileError = class extends Error {
13
13
  };
14
14
  var CANONICAL_HASH_RE = /^[0-9a-f]{128}$/;
15
15
  var SENTINEL_RE = /^unresolved-[0-9a-f]{64}$/;
16
+ var HASHED_PEER_SET_RE = /^[0-9a-f]{16,}$/;
16
17
  function isCanonicalHash(s) {
17
18
  return CANONICAL_HASH_RE.test(s);
18
19
  }
19
20
  function isSentinelPatch(s) {
20
21
  return SENTINEL_RE.test(s);
21
22
  }
23
+ function isHashedPeerSetToken(seg) {
24
+ if (seg.startsWith("patch_hash=")) return false;
25
+ return HASHED_PEER_SET_RE.test(seg);
26
+ }
22
27
 
23
28
  // src/main/ts/graph.ts
24
29
  var GraphError = class extends Error {
@@ -227,7 +232,7 @@ function validate(s) {
227
232
  throw new GraphError("INVARIANT_VIOLATION", `node id ${id} disagrees with derived id ${expected.join(" or ")}`);
228
233
  }
229
234
  const peerEdgeTargets = (s.outgoing.get(id) ?? []).filter((e) => e.kind === "peer").map((e) => stripPeerContextFromNodeId(e.dst)).sort();
230
- const peerCtx = node.peerContext.map(stripPeerContextFromNodeId).sort();
235
+ const peerCtx = node.peerContext.filter((p) => !isHashedPeerSetToken(stripPeerContextFromNodeId(p))).map(stripPeerContextFromNodeId).sort();
231
236
  if (peerEdgeTargets.length !== peerCtx.length || peerEdgeTargets.some((t, i) => t !== peerCtx[i])) {
232
237
  throw new GraphError("INVARIANT_VIOLATION", `peer edges of ${id} disagree with peerContext`);
233
238
  }
@@ -15,12 +15,17 @@ var LockfileError = class extends Error {
15
15
  };
16
16
  var CANONICAL_HASH_RE = /^[0-9a-f]{128}$/;
17
17
  var SENTINEL_RE = /^unresolved-[0-9a-f]{64}$/;
18
+ var HASHED_PEER_SET_RE = /^[0-9a-f]{16,}$/;
18
19
  function isCanonicalHash(s) {
19
20
  return CANONICAL_HASH_RE.test(s);
20
21
  }
21
22
  function isSentinelPatch(s) {
22
23
  return SENTINEL_RE.test(s);
23
24
  }
25
+ function isHashedPeerSetToken(seg) {
26
+ if (seg.startsWith("patch_hash=")) return false;
27
+ return HASHED_PEER_SET_RE.test(seg);
28
+ }
24
29
 
25
30
  // src/main/ts/graph.ts
26
31
  var GraphError = class extends Error {
@@ -240,7 +245,7 @@ function validate(s) {
240
245
  throw new GraphError("INVARIANT_VIOLATION", `node id ${id} disagrees with derived id ${expected.join(" or ")}`);
241
246
  }
242
247
  const peerEdgeTargets = (s.outgoing.get(id) ?? []).filter((e) => e.kind === "peer").map((e) => stripPeerContextFromNodeId(e.dst)).sort();
243
- const peerCtx = node.peerContext.map(stripPeerContextFromNodeId).sort();
248
+ const peerCtx = node.peerContext.filter((p) => !isHashedPeerSetToken(stripPeerContextFromNodeId(p))).map(stripPeerContextFromNodeId).sort();
244
249
  if (peerEdgeTargets.length !== peerCtx.length || peerEdgeTargets.some((t, i) => t !== peerCtx[i])) {
245
250
  throw new GraphError("INVARIANT_VIOLATION", `peer edges of ${id} disagree with peerContext`);
246
251
  }
@@ -1262,6 +1267,7 @@ function parseFamily(input, _options, config) {
1262
1267
  if (entry.dev === true) nodeSide.dev = true;
1263
1268
  if (entry.optional === true) nodeSide.optional = true;
1264
1269
  if (entry.peer === true) nodeSide.peer = true;
1270
+ if (entry.extraneous === true) nodeSide.extraneous = true;
1265
1271
  config.hooks?.captureEntry?.(srcId, entry);
1266
1272
  const isRoot = path === "";
1267
1273
  const isWorkspaceMember = workspaceByPath.has(path);
@@ -1391,10 +1397,13 @@ function stringifyFamily(graph, config, options = {}) {
1391
1397
  }
1392
1398
  for (const node of workspaceMembers) {
1393
1399
  packages[node.workspacePath] = buildWorkspaceMemberEntry(graph, node, sidecar, emitDiagnostic);
1394
- packages[`node_modules/${node.name}`] = {
1395
- resolved: node.workspacePath,
1396
- link: true
1397
- };
1400
+ const extraneous = sidecar?.nodes.get(node.id)?.extraneous === true;
1401
+ if (!extraneous) {
1402
+ packages[`node_modules/${node.name}`] = {
1403
+ resolved: node.workspacePath,
1404
+ link: true
1405
+ };
1406
+ }
1398
1407
  }
1399
1408
  for (const node of graph.nodes()) {
1400
1409
  if (rootNode !== void 0 && node.id === rootNode.id) continue;
@@ -15,12 +15,17 @@ var LockfileError = class extends Error {
15
15
  };
16
16
  var CANONICAL_HASH_RE = /^[0-9a-f]{128}$/;
17
17
  var SENTINEL_RE = /^unresolved-[0-9a-f]{64}$/;
18
+ var HASHED_PEER_SET_RE = /^[0-9a-f]{16,}$/;
18
19
  function isCanonicalHash(s) {
19
20
  return CANONICAL_HASH_RE.test(s);
20
21
  }
21
22
  function isSentinelPatch(s) {
22
23
  return SENTINEL_RE.test(s);
23
24
  }
25
+ function isHashedPeerSetToken(seg) {
26
+ if (seg.startsWith("patch_hash=")) return false;
27
+ return HASHED_PEER_SET_RE.test(seg);
28
+ }
24
29
 
25
30
  // src/main/ts/graph.ts
26
31
  var GraphError = class extends Error {
@@ -240,7 +245,7 @@ function validate(s) {
240
245
  throw new GraphError("INVARIANT_VIOLATION", `node id ${id} disagrees with derived id ${expected.join(" or ")}`);
241
246
  }
242
247
  const peerEdgeTargets = (s.outgoing.get(id) ?? []).filter((e) => e.kind === "peer").map((e) => stripPeerContextFromNodeId(e.dst)).sort();
243
- const peerCtx = node.peerContext.map(stripPeerContextFromNodeId).sort();
248
+ const peerCtx = node.peerContext.filter((p) => !isHashedPeerSetToken(stripPeerContextFromNodeId(p))).map(stripPeerContextFromNodeId).sort();
244
249
  if (peerEdgeTargets.length !== peerCtx.length || peerEdgeTargets.some((t, i) => t !== peerCtx[i])) {
245
250
  throw new GraphError("INVARIANT_VIOLATION", `peer edges of ${id} disagree with peerContext`);
246
251
  }
@@ -1262,6 +1267,7 @@ function parseFamily(input, _options, config) {
1262
1267
  if (entry.dev === true) nodeSide.dev = true;
1263
1268
  if (entry.optional === true) nodeSide.optional = true;
1264
1269
  if (entry.peer === true) nodeSide.peer = true;
1270
+ if (entry.extraneous === true) nodeSide.extraneous = true;
1265
1271
  config.hooks?.captureEntry?.(srcId, entry);
1266
1272
  const isRoot = path === "";
1267
1273
  const isWorkspaceMember = workspaceByPath.has(path);
@@ -1391,10 +1397,13 @@ function stringifyFamily(graph, config, options = {}) {
1391
1397
  }
1392
1398
  for (const node of workspaceMembers) {
1393
1399
  packages[node.workspacePath] = buildWorkspaceMemberEntry(graph, node, sidecar, emitDiagnostic);
1394
- packages[`node_modules/${node.name}`] = {
1395
- resolved: node.workspacePath,
1396
- link: true
1397
- };
1400
+ const extraneous = sidecar?.nodes.get(node.id)?.extraneous === true;
1401
+ if (!extraneous) {
1402
+ packages[`node_modules/${node.name}`] = {
1403
+ resolved: node.workspacePath,
1404
+ link: true
1405
+ };
1406
+ }
1398
1407
  }
1399
1408
  for (const node of graph.nodes()) {
1400
1409
  if (rootNode !== void 0 && node.id === rootNode.id) continue;
@@ -15,12 +15,17 @@ var LockfileError = class extends Error {
15
15
  };
16
16
  var CANONICAL_HASH_RE = /^[0-9a-f]{128}$/;
17
17
  var SENTINEL_RE = /^unresolved-[0-9a-f]{64}$/;
18
+ var HASHED_PEER_SET_RE = /^[0-9a-f]{16,}$/;
18
19
  function isCanonicalHash(s) {
19
20
  return CANONICAL_HASH_RE.test(s);
20
21
  }
21
22
  function isSentinelPatch(s) {
22
23
  return SENTINEL_RE.test(s);
23
24
  }
25
+ function isHashedPeerSetToken(seg) {
26
+ if (seg.startsWith("patch_hash=")) return false;
27
+ return HASHED_PEER_SET_RE.test(seg);
28
+ }
24
29
 
25
30
  // src/main/ts/graph.ts
26
31
  var GraphError = class extends Error {
@@ -229,7 +234,7 @@ function validate(s) {
229
234
  throw new GraphError("INVARIANT_VIOLATION", `node id ${id} disagrees with derived id ${expected.join(" or ")}`);
230
235
  }
231
236
  const peerEdgeTargets = (s.outgoing.get(id) ?? []).filter((e) => e.kind === "peer").map((e) => stripPeerContextFromNodeId(e.dst)).sort();
232
- const peerCtx = node.peerContext.map(stripPeerContextFromNodeId).sort();
237
+ const peerCtx = node.peerContext.filter((p) => !isHashedPeerSetToken(stripPeerContextFromNodeId(p))).map(stripPeerContextFromNodeId).sort();
233
238
  if (peerEdgeTargets.length !== peerCtx.length || peerEdgeTargets.some((t, i) => t !== peerCtx[i])) {
234
239
  throw new GraphError("INVARIANT_VIOLATION", `peer edges of ${id} disagree with peerContext`);
235
240
  }
@@ -973,8 +978,7 @@ function readBlockMap(reader, baseIndent) {
973
978
  const restValue = restClean.replace(/^ +/, "");
974
979
  reader.pos++;
975
980
  if (restValue === "") {
976
- const child = readBlockMap(reader, baseIndent + 2);
977
- out[key] = child;
981
+ out[key] = peekIsBlockSequence(reader, baseIndent) ? readBlockSequence(reader, baseIndent) : readBlockMap(reader, baseIndent + 2);
978
982
  } else if (restValue === "|" || restValue === ">") {
979
983
  while (reader.pos < reader.lines.length) {
980
984
  const next = reader.lines[reader.pos];
@@ -990,6 +994,40 @@ function readBlockMap(reader, baseIndent) {
990
994
  }
991
995
  return out;
992
996
  }
997
+ function peekIsBlockSequence(reader, baseIndent) {
998
+ for (let i = reader.pos; i < reader.lines.length; i++) {
999
+ const line = reader.lines[i];
1000
+ if (line === void 0) continue;
1001
+ if (isBlankOrComment(line)) continue;
1002
+ const indent = leadingSpaces(line);
1003
+ if (indent < baseIndent) return false;
1004
+ const content = line.slice(indent);
1005
+ return content === "-" || content.startsWith("- ");
1006
+ }
1007
+ return false;
1008
+ }
1009
+ function readBlockSequence(reader, baseIndent) {
1010
+ const out = [];
1011
+ while (reader.pos < reader.lines.length) {
1012
+ const line = reader.lines[reader.pos];
1013
+ if (line === void 0) {
1014
+ reader.pos++;
1015
+ continue;
1016
+ }
1017
+ if (isBlankOrComment(line)) {
1018
+ reader.pos++;
1019
+ continue;
1020
+ }
1021
+ const indent = leadingSpaces(line);
1022
+ if (indent < baseIndent) break;
1023
+ const content = line.slice(indent);
1024
+ if (content !== "-" && !content.startsWith("- ")) break;
1025
+ const itemRaw = content === "-" ? "" : content.slice(2);
1026
+ out.push(parseInlineValue(stripInlineComment(itemRaw).trim()));
1027
+ reader.pos++;
1028
+ }
1029
+ return out;
1030
+ }
993
1031
  function findKeyColon(content) {
994
1032
  let inQuote = null;
995
1033
  let depth = 0;
@@ -1289,12 +1327,18 @@ function isPlainObject2(value) {
1289
1327
  return value !== null && typeof value === "object" && !Array.isArray(value);
1290
1328
  }
1291
1329
  function resolvePeerTargetById(seenIds, peerName, peerVersion) {
1292
- const bareId = `${peerName}@${peerVersion}`;
1293
- if (seenIds.has(bareId)) return bareId;
1330
+ const fullId = `${peerName}@${peerVersion}`;
1331
+ if (seenIds.has(fullId)) return fullId;
1332
+ const suffixStart = peerVersion.indexOf("(");
1333
+ const bareVersion = suffixStart === -1 ? peerVersion : peerVersion.slice(0, suffixStart);
1334
+ const bareId = `${peerName}@${bareVersion}`;
1335
+ if (bareId !== fullId && seenIds.has(bareId)) return bareId;
1336
+ const prefix = bareId + "(";
1337
+ let best;
1294
1338
  for (const id of seenIds) {
1295
- if (id.startsWith(bareId + "(")) return id;
1339
+ if (id.startsWith(prefix) && (best === void 0 || id < best)) best = id;
1296
1340
  }
1297
- return void 0;
1341
+ return best;
1298
1342
  }
1299
1343
  function resolveLinkPath(importerPath, relTarget) {
1300
1344
  if (importerPath === "." || importerPath === "") {
@@ -1340,6 +1384,7 @@ function tarballPayloadOf(entry, subject, diagnostics) {
1340
1384
  }
1341
1385
  if (Array.isArray(entry.cpu)) payload.cpu = entry.cpu.slice();
1342
1386
  if (Array.isArray(entry.os)) payload.os = entry.os.slice();
1387
+ if (Array.isArray(entry.libc)) payload.libc = entry.libc.slice();
1343
1388
  if (entry.hasBin === true) payload.bin = "true";
1344
1389
  if (typeof entry.deprecated === "string") payload.deprecated = entry.deprecated;
1345
1390
  return Object.keys(payload).length === 0 ? void 0 : payload;
@@ -1725,12 +1770,67 @@ function stringify(graph, options = {}) {
1725
1770
  packages[key] = buildPackageEntry(graph, sidecar, node);
1726
1771
  }
1727
1772
  out.packages = packages;
1773
+ assertResolveValid(graph, out, rootNode, resolvedNodes, emitDiagnostic);
1728
1774
  const text = emitYaml(out, {
1729
1775
  topLevelOrder: TOP_LEVEL_ORDER,
1730
1776
  topLevelSectionKeys: TOP_LEVEL_SECTION_KEYS
1731
1777
  });
1732
1778
  return options.lineEnding === "crlf" ? text.replace(/\n/g, "\r\n") : text;
1733
1779
  }
1780
+ function assertResolveValid(graph, out, rootNode, resolvedNodes, onDiagnostic) {
1781
+ const seenIds = new Set(resolvedNodes.map((n) => n.id));
1782
+ const importersMap = isPlainObject2(out.importers) ? out.importers : void 0;
1783
+ const consumerBlockOf = (consumer) => {
1784
+ const path2 = consumer.id === rootNode?.id ? "." : consumer.workspacePath ?? consumer.name;
1785
+ if (importersMap !== void 0) {
1786
+ const block = importersMap[path2];
1787
+ return isPlainObject2(block) ? block : void 0;
1788
+ }
1789
+ return consumer.id === rootNode?.id ? out : void 0;
1790
+ };
1791
+ const packagesMap = isPlainObject2(out.packages) ? out.packages : void 0;
1792
+ const packageBlockOf = (pkg) => {
1793
+ const entry = packagesMap?.[packagesKeyForNode(pkg)];
1794
+ return isPlainObject2(entry) ? entry : void 0;
1795
+ };
1796
+ const slotValue = (block, blockNames, seg) => {
1797
+ for (const blockName of blockNames) {
1798
+ const sub = block[blockName];
1799
+ if (!isPlainObject2(sub)) continue;
1800
+ const raw = sub[seg];
1801
+ if (typeof raw === "string") return raw;
1802
+ }
1803
+ return void 0;
1804
+ };
1805
+ const isImporter = (node) => node.id === rootNode?.id || node.workspacePath !== void 0 && node.workspacePath !== "";
1806
+ const consumerBlockNames = ["dependencies", "devDependencies", "optionalDependencies"];
1807
+ const packageBlockNames = ["dependencies", "optionalDependencies"];
1808
+ for (const consumer of graph.nodes()) {
1809
+ const consumerIsImporter = isImporter(consumer);
1810
+ if (!consumerIsImporter && !seenIds.has(consumer.id)) continue;
1811
+ const block = consumerIsImporter ? consumerBlockOf(consumer) : packageBlockOf(consumer);
1812
+ if (block === void 0) continue;
1813
+ const blockNames = consumerIsImporter ? consumerBlockNames : packageBlockNames;
1814
+ for (const edge of graph.out(consumer.id)) {
1815
+ if (edge.kind !== "dep" && edge.kind !== "dev" && edge.kind !== "optional") continue;
1816
+ const dst = graph.getNode(edge.dst);
1817
+ if (dst === void 0) continue;
1818
+ if (dst.workspacePath !== void 0 && dst.workspacePath !== "") continue;
1819
+ if (!consumerIsImporter && (dst.id === consumer.id || dst.id === rootNode?.id)) continue;
1820
+ const seg = edge.attrs?.alias ?? dst.name;
1821
+ const value = slotValue(block, blockNames, seg);
1822
+ const resolved = value === void 0 ? void 0 : resolveDependencyTarget(seenIds, seg, value) ?? resolveAliasedDependencyTarget(seenIds, value);
1823
+ if (resolved !== dst.id) {
1824
+ onDiagnostic({
1825
+ code: "LAYOUT_RESOLVE_VIOLATION",
1826
+ severity: "error",
1827
+ subject: { src: edge.src, dst: edge.dst, kind: edge.kind },
1828
+ message: `INV-RESOLVE violated: ${consumer.id} resolves ${JSON.stringify(seg)} to ${value === void 0 ? "(no slot)" : resolved === void 0 ? `${JSON.stringify(value)} \u2192 (nothing)` : resolved}, expected ${dst.id} (pnpm-v5 encoding defect \u2014 ADR-0028 INV-RESOLVE)`
1829
+ });
1830
+ }
1831
+ }
1832
+ }
1833
+ }
1734
1834
  function enrich(graph, options = {}) {
1735
1835
  const sidecar = sidecarByGraph.get(graph);
1736
1836
  const diagnostics = [];
@@ -2001,6 +2101,12 @@ function nodeIdToDependencyValue(node) {
2001
2101
  const tail = node.peerContext.length === 0 ? "" : node.peerContext.map((p) => `_${p}`).join("");
2002
2102
  return `${node.version}${tail}`;
2003
2103
  }
2104
+ function aliasedDependencySlot(edge, dst) {
2105
+ const bareValue = nodeIdToDependencyValue(dst);
2106
+ const alias = edge.attrs?.alias;
2107
+ if (alias === void 0) return { key: dst.name, value: bareValue };
2108
+ return { key: alias, value: `${dst.name}@${bareValue}` };
2109
+ }
2004
2110
  function buildImporterEntry(graph, sidecar, node, importerPath) {
2005
2111
  const entry = {};
2006
2112
  if (node === void 0) return entry;
@@ -2020,12 +2126,15 @@ function buildImporterEntry(graph, sidecar, node, importerPath) {
2020
2126
  const isWorkspaceTarget = dst.workspacePath !== void 0 && dst.workspacePath !== "";
2021
2127
  const edgeKey = `${edge.src}\0${edge.kind}\0${edge.dst}`;
2022
2128
  const edgeSc = sidecar?.importerEdges.get(edgeKey);
2129
+ const slot = aliasedDependencySlot(edge, dst);
2130
+ const isAliased = edge.attrs?.alias !== void 0;
2023
2131
  const range = edge.attrs?.range;
2024
- const specifierFromSidecar = importerSpecs?.[dst.name];
2025
- const specifier = edgeSc?.specifier ?? specifierFromSidecar ?? range ?? dst.version;
2026
- const version = isWorkspaceTarget ? `link:${relativeImporterPath(importerPath, dst.workspacePath ?? dst.name)}` : edgeSc?.resolvedVersion ?? nodeIdToDependencyValue(dst);
2027
- blocks[edge.kind][dst.name] = version;
2028
- specifiers[dst.name] = specifier;
2132
+ const specifierFromSidecar = importerSpecs?.[slot.key];
2133
+ const captureIsAliasConsistent = edgeSc?.resolvedVersion?.startsWith(`${dst.name}@`) === true;
2134
+ const specifier = isAliased ? range ?? specifierFromSidecar ?? edgeSc?.specifier ?? dst.version : edgeSc?.specifier ?? specifierFromSidecar ?? range ?? dst.version;
2135
+ const version = isWorkspaceTarget ? `link:${relativeImporterPath(importerPath, dst.workspacePath ?? dst.name)}` : isAliased ? captureIsAliasConsistent ? edgeSc.resolvedVersion : slot.value : edgeSc?.resolvedVersion ?? slot.value;
2136
+ blocks[edge.kind][slot.key] = version;
2137
+ specifiers[slot.key] = specifier;
2029
2138
  }
2030
2139
  if (Object.keys(specifiers).length > 0) {
2031
2140
  entry.specifiers = sortRecord(specifiers);
@@ -2084,7 +2193,8 @@ function buildPackageEntry(graph, sidecar, representative) {
2084
2193
  if (dst.workspacePath !== void 0 && dst.workspacePath !== "") continue;
2085
2194
  if (dst.id === sidecar?.rootId) continue;
2086
2195
  const block = blocks[edge.kind];
2087
- block[dst.name] = nodeIdToDependencyValue(dst);
2196
+ const slot = aliasedDependencySlot(edge, dst);
2197
+ block[slot.key] = slot.value;
2088
2198
  }
2089
2199
  for (const [kind, blockName] of [["dep", "dependencies"], ["optional", "optionalDependencies"]]) {
2090
2200
  const block = blocks[kind];