@vltpkg/graph 1.0.0-rc.11 → 1.0.0-rc.13

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.
@@ -62,8 +62,9 @@ export declare const endPeerPlacement: (peerContext: PeerContext, nextDeps: Depe
62
62
  /**
63
63
  * Try to resolve peer dependencies using already seen target
64
64
  * values from the current peer context set.
65
+ * @param {PeerContext} currentContext The current peer context (may be forked from original)
65
66
  */
66
- resolvePeerDeps: () => void;
67
+ resolvePeerDeps: (currentContext: PeerContext) => void;
67
68
  };
68
69
  /**
69
70
  * Given an array of processed results for the current level dependencies
@@ -1 +1 @@
1
- {"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC;;GAEG;AACH,eAAO,MAAM,uBAAuB,gBACrB,WAAW,GAAG,SAAS,KACnC,MAAM,GAAG,SAKX,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,SACtB,IAAI,SACH,gBAAgB,KACtB,OAkBF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,YAC9B,qBAAqB,EAAE,KAC/B,qBAAqB,EAUpB,CAAA;AAQJ,eAAO,MAAM,yBAAyB,gBACvB,WAAW,WACf,qBAAqB,EAAE,KAC/B,OAgBF,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,gBACrB,WAAW,WACf,qBAAqB,EAAE,YACtB,IAAI,aACH,QAAQ,KAClB,OAsEF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,UACnB,KAAK,eACC,WAAW,WACf,qBAAqB,EAAE,KAC/B,WAqCF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gBAChB,WAAW,YACd,QAAQ,YACR,IAAI,WACL,WAAW;;;CA4CrB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,gBACd,WAAW,YACd,UAAU,EAAE,gBACR,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,SAChD,KAAK,QACN,IAAI,YACA,IAAI,QACR,IAAI,QACJ,kBAAkB,iBACT,qBAAqB,EAAE;IAEtC;;OAEG;;;;;;IA2CH;;;OAGG;;CAsCH,CAAA;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,UAC1B,KAAK,sBACQ,sBAAsB,EAAE,SAiE7C,CAAA"}
1
+ {"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC;;GAEG;AACH,eAAO,MAAM,uBAAuB,gBACrB,WAAW,GAAG,SAAS,KACnC,MAAM,GAAG,SAKX,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,SACtB,IAAI,SACH,gBAAgB,KACtB,OAkBF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,YAC9B,qBAAqB,EAAE,KAC/B,qBAAqB,EAUpB,CAAA;AAQJ,eAAO,MAAM,yBAAyB,gBACvB,WAAW,WACf,qBAAqB,EAAE,KAC/B,OAgBF,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,gBACrB,WAAW,WACf,qBAAqB,EAAE,YACtB,IAAI,aACH,QAAQ,KAClB,OAsFF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,UACnB,KAAK,eACC,WAAW,WACf,qBAAqB,EAAE,KAC/B,WAoDF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gBAChB,WAAW,YACd,QAAQ,YACR,IAAI,WACL,WAAW;;;CA4CrB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,gBACd,WAAW,YACd,UAAU,EAAE,gBACR,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,SAChD,KAAK,QACN,IAAI,YACA,IAAI,QACR,IAAI,QACJ,kBAAkB,iBACT,qBAAqB,EAAE;IAEtC;;OAEG;;;;;;IA2CH;;;;OAIG;sCAC+B,WAAW;CAwE7C,CAAA;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,UAC1B,KAAK,sBACQ,sBAAsB,EAAE,SAmE7C,CAAA"}
@@ -113,17 +113,25 @@ export const addEntriesToPeerContext = (peerContext, entries, fromNode, monorepo
113
113
  [...entry.specs].every(s => satisfies(target.id, s, fromNode.location, fromNode.projectRoot, monorepo))) {
114
114
  if (target.id !== entry.target?.id &&
115
115
  target.version !== entry.target?.version) {
116
- // we have a compatible entry that has a new, compatible target
117
- // so we need to update all dependents to point to the new target
118
- for (const dependents of entry.contextDependents) {
119
- const edge = dependents.edgesOut.get(name);
120
- if (edge?.to && edge.to !== target) {
121
- edge.to.edgesIn.delete(edge);
122
- edge.to = target;
123
- target.edgesIn.add(edge);
116
+ // Check if the existing target also satisfies the new spec.
117
+ // If it does, we should keep the existing target rather than
118
+ // switching to the new one. This preserves pinned versions
119
+ // and prevents unnecessary target changes.
120
+ const existingTargetSatisfiesNewSpec = entry.target &&
121
+ satisfies(entry.target.id, spec, fromNode.location, fromNode.projectRoot, monorepo);
122
+ if (!existingTargetSatisfiesNewSpec) {
123
+ // Only update all dependents to point to the new target if
124
+ // the existing target doesn't satisfy the new spec
125
+ for (const dependents of entry.contextDependents) {
126
+ const edge = dependents.edgesOut.get(name);
127
+ if (edge?.to && edge.to !== target) {
128
+ edge.to.edgesIn.delete(edge);
129
+ edge.to = target;
130
+ target.edgesIn.add(edge);
131
+ }
124
132
  }
133
+ entry.target = target;
125
134
  }
126
- entry.target = target;
127
135
  }
128
136
  // otherwise sets the value in case it was nullish
129
137
  entry.target ??= target;
@@ -146,12 +154,17 @@ export const forkPeerContext = (graph, peerContext, entries) => {
146
154
  graph.peerContexts[nextPeerContext.index] = nextPeerContext;
147
155
  // copy existing entries marking them as inactive, it's also important
148
156
  // to note that specs and contextDependents are new objects so that changes
149
- // to those in the new context do not affect the previous one
157
+ // to those in the new context do not affect the previous one.
158
+ // IMPORTANT: We preserve the target from the parent context so that packages
159
+ // in the forked context can still resolve peer deps to the same version as
160
+ // the parent context. This fixes an issue where forked contexts would lose
161
+ // track of already-resolved peer dependencies (like a pinned typescript version)
162
+ // and resolve to different versions.
150
163
  for (const [name, entry] of peerContext.entries()) {
151
164
  nextPeerContext.set(name, {
152
165
  active: false,
153
166
  specs: new Set(entry.specs),
154
- target: undefined,
167
+ target: entry.target,
155
168
  type: entry.type,
156
169
  contextDependents: new Set(entry.contextDependents),
157
170
  });
@@ -161,10 +174,17 @@ export const forkPeerContext = (graph, peerContext, entries) => {
161
174
  for (const entry of entries) {
162
175
  const { dependent, spec, target, type } = entry;
163
176
  const name = target?.name /* c8 ignore next */ ?? spec.final.name;
177
+ // IMPORTANT: If the new entry has no target but the parent context had one,
178
+ // preserve the parent's target. This ensures that when a fork happens due to
179
+ // spec "incompatibility" (e.g., pinned version vs range), we don't lose the
180
+ // already-resolved target. The satisfies check in resolvePeerDeps will later
181
+ // verify if the preserved target actually satisfies the new spec.
182
+ const existingEntry = nextPeerContext.get(name);
183
+ const preservedTarget = !target && existingEntry?.target ? existingEntry.target : target;
164
184
  const newEntry = {
165
185
  active: true,
166
186
  specs: new Set([spec]),
167
- target,
187
+ target: preservedTarget,
168
188
  type,
169
189
  contextDependents: dependent ? new Set([dependent]) : new Set(),
170
190
  };
@@ -255,8 +275,9 @@ export const endPeerPlacement = (peerContext, nextDeps, nextPeerDeps, graph, spe
255
275
  /**
256
276
  * Try to resolve peer dependencies using already seen target
257
277
  * values from the current peer context set.
278
+ * @param {PeerContext} currentContext The current peer context (may be forked from original)
258
279
  */
259
- resolvePeerDeps: () => {
280
+ resolvePeerDeps: (currentContext) => {
260
281
  // iterate on the set of peer dependencies of the current node
261
282
  // and try to resolve them from the existing peer context set,
262
283
  // when possible, add them as edges in the graph right away, if not,
@@ -265,9 +286,24 @@ export const endPeerPlacement = (peerContext, nextDeps, nextPeerDeps, graph, spe
265
286
  for (const nextDep of nextPeerDeps.values()) {
266
287
  const { spec, type } = nextDep;
267
288
  if (type === 'peer' || type === 'peerOptional') {
268
- // try to retrieve an entry for that peer dep from
269
- // the current peer context set
270
- const entry = peerContext.get(spec.final.name);
289
+ // FIRST: Check if there's a sibling dependency from the parent
290
+ // that specifies this same package. Sibling deps take priority
291
+ // because they represent the workspace's direct dependency,
292
+ // which should be preferred over versions from other workspaces
293
+ // that may have been added to the peer context earlier.
294
+ const siblingEntry = queuedEntries.find(e => (e.target?.name ?? e.spec.final.name) === spec.final.name);
295
+ if (siblingEntry?.target &&
296
+ !node.edgesOut.has(spec.final.name) &&
297
+ satisfies(siblingEntry.target.id, spec, fromNode.location, fromNode.projectRoot, graph.monorepo)) {
298
+ // The sibling's resolved target satisfies the peer spec,
299
+ // use it directly - this prioritizes the workspace's own
300
+ // direct dependency over versions from other workspaces
301
+ graph.addEdge(type, spec, node, siblingEntry.target);
302
+ continue;
303
+ }
304
+ // THEN: Try to retrieve an entry for that peer dep from
305
+ // the current peer context set (which may have been forked)
306
+ const entry = currentContext.get(spec.final.name);
271
307
  if (!node.edgesOut.has(spec.final.name) &&
272
308
  entry?.target &&
273
309
  satisfies(entry.target.id, spec, fromNode.location, fromNode.projectRoot, graph.monorepo)) {
@@ -280,8 +316,14 @@ export const endPeerPlacement = (peerContext, nextDeps, nextPeerDeps, graph, spe
280
316
  // just create a dangling edge
281
317
  graph.addEdge(type, spec, node);
282
318
  }
319
+ else if (siblingEntry &&
320
+ siblingEntry.spec.bareSpec !== spec.bareSpec) {
321
+ // Sibling has a more specific spec for this package,
322
+ // use it when resolving to ensure we get the right version
323
+ nextDeps.push({ ...nextDep, spec: siblingEntry.spec });
324
+ }
283
325
  else {
284
- // could not satisfy from peer context, add to next deps
326
+ // could not satisfy from peer context or sibling, add to next deps
285
327
  nextDeps.push(nextDep);
286
328
  }
287
329
  }
@@ -332,7 +374,9 @@ export const postPlacementPeerCheck = (graph, sortedLevelResults) => {
332
374
  // try to resolve peer dependencies now that
333
375
  // the context is fully set up
334
376
  for (const childDep of sortedChildDeps) {
335
- childDep.updateContext.resolvePeerDeps();
377
+ // Pass the current peerContext (which may have been forked)
378
+ // so resolvePeerDeps uses the correct context with preserved targets
379
+ childDep.updateContext.resolvePeerDeps(childDep.peerContext);
336
380
  childDep.deps = getOrderedDependencies(childDep.deps);
337
381
  }
338
382
  }
@@ -1 +1 @@
1
- {"version":3,"file":"peers.js","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"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","sourcesContent":["// helpers for managing peer dependency resolution\n// during the ideal graph building process.\n\nimport { intersects } from '@vltpkg/semver'\nimport { satisfies } from '@vltpkg/satisfies'\nimport { getDependencies } from '../dependencies.ts'\nimport { getOrderedDependencies } from './get-ordered-dependencies.ts'\nimport type {\n ProcessPlacementResultEntry,\n PeerContext,\n PeerContextEntry,\n PeerContextEntryInput,\n ProcessPlacementResult,\n} from './types.ts'\nimport type { Spec, SpecOptions } from '@vltpkg/spec'\nimport type { DependencySaveType, Manifest } from '@vltpkg/types'\nimport type { Monorepo } from '@vltpkg/workspaces'\nimport type { Dependency } from '../dependencies.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\n\n/**\n * Retrieve a unique hash value for a given peer context set.\n */\nexport const retrievePeerContextHash = (\n peerContext: PeerContext | undefined,\n): string | undefined => {\n // skips creating the initial peer context ref\n if (!peerContext?.index) return undefined\n\n return `ṗ:${peerContext.index}`\n}\n\n/**\n * Checks if a given spec is compatible with the specs already\n * assigned to a peer context entry.\n *\n * Returns true if compatible, false otherwise.\n */\nexport const incompatibleSpecs = (\n spec: Spec,\n entry: PeerContextEntry,\n): boolean => {\n if (entry.specs.size > 0) {\n for (const s of entry.specs) {\n if (\n // only able to check range intersections for registry types\n (spec.type === 'registry' &&\n (!spec.range ||\n !s.range ||\n !intersects(spec.range, s.range))) ||\n // also support types other than registry in case\n // they use the very same bareSpec value\n (spec.type !== 'registry' && spec.bareSpec !== s.bareSpec)\n ) {\n return true\n }\n }\n }\n return false\n}\n\n/**\n * Sort peer context entry inputs for deterministic processing.\n * Orders: non-peer dependencies first, then peer dependencies, alphabetically by name.\n */\nexport const getOrderedPeerContextEntries = (\n entries: PeerContextEntryInput[],\n): PeerContextEntryInput[] =>\n [...entries].sort((a, b) => {\n const aIsPeer =\n a.type === 'peer' || a.type === 'peerOptional' ? 1 : 0\n const bIsPeer =\n b.type === 'peer' || b.type === 'peerOptional' ? 1 : 0\n if (aIsPeer !== bIsPeer) return aIsPeer - bIsPeer\n const aName = a.target?.name ?? a.spec.name\n const bName = b.target?.name ?? b.spec.name\n return aName.localeCompare(bName, 'en')\n })\n\n/*\n * Checks if there are any conflicting versions for a given dependency\n * to be added to a peer context set which will require forking.\n *\n * Returns true if forking is needed, false otherwise.\n */\nexport const checkEntriesToPeerContext = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n): boolean => {\n // check on compatibility of new entries\n for (const { spec, target } of entries) {\n const name = target?.name ?? spec.final.name\n\n // skip any inactive entry\n const entry = peerContext.get(name)\n if (!entry?.active) continue\n\n // validate if the provided spec is compatible with existing specs\n if (incompatibleSpecs(spec, entry)) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Add or update dependencies in a given peer context making sure to check\n * for compatibility with existing dependencies already resolved by a given\n * peer context set. Extra info such as a target or dependent nodes is\n * optional.\n *\n * Returns true if forking is needed, false otherwise.\n */\nexport const addEntriesToPeerContext = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n fromNode: Node,\n monorepo?: Monorepo,\n): boolean => {\n // pre check to see if any of the new entries to be added to the\n // provided peer context set conflicts with existing ones\n // if that's already the case we can skip processing them and\n // will return that a fork is needed right away\n if (checkEntriesToPeerContext(peerContext, entries)) return true\n\n // iterate on every entry to be added to the peer context set\n for (const { dependent, spec, target, type } of entries) {\n const name = target?.name ?? spec.final.name\n\n // if there's no existing entry, create one\n let entry = peerContext.get(name)\n if (!entry) {\n entry = {\n active: true,\n specs: new Set([spec]),\n target,\n type,\n contextDependents: new Set(),\n }\n peerContext.set(name, entry)\n if (dependent) entry.contextDependents.add(dependent)\n continue\n }\n\n // perform an extra check that confirms the new spec does not\n // conflicts with existing specs in this entry, this handles the\n // case of adding sibling deps that conflicts with one another\n if (incompatibleSpecs(spec, entry)) return true\n\n if (\n target &&\n [...entry.specs].every(s =>\n satisfies(\n target.id,\n s,\n fromNode.location,\n fromNode.projectRoot,\n monorepo,\n ),\n )\n ) {\n if (\n target.id !== entry.target?.id &&\n target.version !== entry.target?.version\n ) {\n // we have a compatible entry that has a new, compatible target\n // so we need to update all dependents to point to the new target\n for (const dependents of entry.contextDependents) {\n const edge = dependents.edgesOut.get(name)\n if (edge?.to && edge.to !== target) {\n edge.to.edgesIn.delete(edge)\n edge.to = target\n target.edgesIn.add(edge)\n }\n }\n entry.target = target\n }\n\n // otherwise sets the value in case it was nullish\n entry.target ??= target\n }\n\n // update specs and dependents values\n entry.specs.add(spec)\n if (dependent) entry.contextDependents.add(dependent)\n }\n\n return false\n}\n\n/**\n * Create and returns a forked copy of a given peer context set.\n */\nexport const forkPeerContext = (\n graph: Graph,\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n): PeerContext => {\n // create a new peer context set\n const nextPeerContext: PeerContext = new Map()\n nextPeerContext.index = graph.nextPeerContextIndex()\n // register it in the graph\n graph.peerContexts[nextPeerContext.index] = nextPeerContext\n\n // copy existing entries marking them as inactive, it's also important\n // to note that specs and contextDependents are new objects so that changes\n // to those in the new context do not affect the previous one\n for (const [name, entry] of peerContext.entries()) {\n nextPeerContext.set(name, {\n active: false,\n specs: new Set(entry.specs),\n target: undefined,\n type: entry.type,\n contextDependents: new Set(entry.contextDependents),\n })\n }\n\n // add the new entries to this peer context set, marking them as active\n // these are the entries that were incompatible with the previous context set\n for (const entry of entries) {\n const { dependent, spec, target, type } = entry\n const name = target?.name /* c8 ignore next */ ?? spec.final.name\n const newEntry = {\n active: true,\n specs: new Set([spec]),\n target,\n type,\n contextDependents:\n dependent ? new Set([dependent]) : new Set<Node>(),\n }\n nextPeerContext.set(name, newEntry)\n }\n\n return nextPeerContext\n}\n\n/**\n * Starts the peer dependency placement process\n * for a given node being processed and placed.\n */\nexport const startPeerPlacement = (\n peerContext: PeerContext,\n manifest: Manifest,\n fromNode: Node,\n options: SpecOptions,\n) => {\n // queue entries so that they can be added at the end of the placement\n // process, use a map to ensure deduplication between read json dep\n // values and the resolved edges in the graph\n const queueMap = new Map<string, PeerContextEntryInput>()\n let peerSetHash: string | undefined\n\n if (\n manifest.peerDependencies &&\n Object.keys(manifest.peerDependencies).length > 0\n ) {\n // generates a peer context set hash for nodes that\n // have peer dependencies to be resolved\n peerSetHash = retrievePeerContextHash(peerContext)\n\n // get any potential sibling dependency from the\n // parent node that might have not been parsed yet\n const siblingDeps = getDependencies(fromNode, {\n ...options,\n registry: fromNode.registry,\n })\n for (const [depName, dep] of siblingDeps) {\n queueMap.set(depName, dep)\n }\n\n // collect the already parsed nodes and add those to the\n // list of entries to be added to the peer context set\n for (const edge of fromNode.edgesOut.values()) {\n queueMap.set(edge.name, {\n spec: edge.spec,\n target: edge.to,\n type: edge.type,\n })\n }\n }\n\n return {\n peerSetHash,\n // Sort queuedEntries for deterministic order\n queuedEntries: getOrderedPeerContextEntries([\n ...queueMap.values(),\n ]),\n }\n}\n\n/**\n * Ends the peer dependency placement process, returning the functions that\n * are going to be used to update the peer context set, forking when needed\n * and resolving peer dependencies if possible.\n */\nexport const endPeerPlacement = (\n peerContext: PeerContext,\n nextDeps: Dependency[],\n nextPeerDeps: Map<string, Dependency> & { id?: number },\n graph: Graph,\n spec: Spec,\n fromNode: Node,\n node: Node,\n type: DependencySaveType,\n queuedEntries: PeerContextEntryInput[],\n) => ({\n /**\n * Add the new entries to the current peer context set.\n */\n putEntries: () => {\n // keep track of whether we need to fork the current peer context set\n let needsToForkPeerContext = false\n // add queued entries from this node parents along\n // with a self-ref to the current peer context set\n const prevEntries = [\n ...queuedEntries,\n /* ref itself */ {\n spec,\n target: node,\n type,\n },\n ]\n addEntriesToPeerContext(\n peerContext,\n prevEntries,\n fromNode,\n graph.monorepo,\n )\n\n // add this node's direct dependencies next\n const nextEntries = [\n ...nextDeps.map(dep => ({ ...dep, dependent: node })),\n ...[...nextPeerDeps.values()].map(dep => ({\n ...dep,\n dependent: node,\n })),\n ]\n if (nextEntries.length > 0) {\n needsToForkPeerContext = addEntriesToPeerContext(\n peerContext,\n nextEntries,\n node,\n graph.monorepo,\n )\n }\n\n // returns all entries that need to be added to a forked\n // context or undefined if the current context was updated directly\n return needsToForkPeerContext ? nextEntries : undefined\n },\n\n /**\n * Try to resolve peer dependencies using already seen target\n * values from the current peer context set.\n */\n resolvePeerDeps: () => {\n // iterate on the set of peer dependencies of the current node\n // and try to resolve them from the existing peer context set,\n // when possible, add them as edges in the graph right away, if not,\n // then we move them back to the `nextDeps` list for processing\n // along with the rest of the regular dependencies\n for (const nextDep of nextPeerDeps.values()) {\n const { spec, type } = nextDep\n if (type === 'peer' || type === 'peerOptional') {\n // try to retrieve an entry for that peer dep from\n // the current peer context set\n const entry = peerContext.get(spec.final.name)\n if (\n !node.edgesOut.has(spec.final.name) &&\n entry?.target &&\n satisfies(\n entry.target.id,\n spec,\n fromNode.location,\n fromNode.projectRoot,\n graph.monorepo,\n )\n ) {\n // entry satisfied, create edge in the graph\n graph.addEdge(type, spec, node, entry.target)\n entry.specs.add(spec.final)\n } else if (type === 'peerOptional') {\n // skip unsatisfied peerOptional dependencies,\n // just create a dangling edge\n graph.addEdge(type, spec, node)\n } else {\n // could not satisfy from peer context, add to next deps\n nextDeps.push(nextDep)\n }\n }\n }\n },\n})\n\n/**\n * Given an array of processed results for the current level dependencies\n * being placed in the currently building ideal graph, traverse its direct\n * dependencies and track peer dependencies in their appropriate peer context\n * sets, forking as needed and resolving peer dependencies using suitable\n * nodes already present in the graph if possible.\n */\nexport const postPlacementPeerCheck = (\n graph: Graph,\n sortedLevelResults: ProcessPlacementResult[],\n) => {\n // Update peer contexts in a sorted manner after processing all nodes\n // at a given level to ensure deterministic behavior when it comes to\n // forking new peer contexts\n for (const childDepsToProcess of sortedLevelResults) {\n // Sort childDepsToProcess deterministically by node.id\n const sortedChildDeps = [...childDepsToProcess].sort((a, b) =>\n a.node.id.localeCompare(b.node.id, 'en'),\n )\n\n const needsForking = new Map<\n ProcessPlacementResultEntry,\n {\n dependent: Node\n spec: Spec\n type: DependencySaveType\n }[]\n >()\n // first iterate on all child deps, adding entries to the current\n // context and collect the information on which ones need forking\n for (const childDep of sortedChildDeps) {\n const needsFork = childDep.updateContext.putEntries()\n if (needsFork) {\n needsForking.set(childDep, needsFork)\n }\n }\n\n // Sort needsForking entries before iterating (Map iteration order = insertion order)\n const sortedNeedsForkingEntries = [\n ...needsForking.entries(),\n ].sort(([a], [b]) => a.node.id.localeCompare(b.node.id, 'en'))\n\n // then iterate again, forking contexts as needed but also try to\n // reuse the context of the previous sibling if possible\n let prevContext\n for (const [childDep, nextEntries] of sortedNeedsForkingEntries) {\n if (\n prevContext &&\n !checkEntriesToPeerContext(prevContext, nextEntries)\n ) {\n // the context of the previous sibling can be reused\n addEntriesToPeerContext(\n prevContext,\n nextEntries,\n childDep.node,\n graph.monorepo,\n )\n childDep.peerContext = prevContext\n continue\n }\n childDep.peerContext = forkPeerContext(\n graph,\n childDep.peerContext,\n nextEntries,\n )\n prevContext = childDep.peerContext\n }\n // try to resolve peer dependencies now that\n // the context is fully set up\n for (const childDep of sortedChildDeps) {\n childDep.updateContext.resolvePeerDeps()\n childDep.deps = getOrderedDependencies(childDep.deps)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"peers.js","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,2CAA2C;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAetE;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,WAAoC,EAChB,EAAE;IACtB,8CAA8C;IAC9C,IAAI,CAAC,WAAW,EAAE,KAAK;QAAE,OAAO,SAAS,CAAA;IAEzC,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE,CAAA;AACjC,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAU,EACV,KAAuB,EACd,EAAE;IACX,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5B;YACE,4DAA4D;YAC5D,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU;gBACvB,CAAC,CAAC,IAAI,CAAC,KAAK;oBACV,CAAC,CAAC,CAAC,KAAK;oBACR,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtC,iDAAiD;gBACjD,wCAAwC;gBACxC,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,CAAC,EAC1D,CAAC;gBACD,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAC1C,OAAgC,EACP,EAAE,CAC3B,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;IACzB,MAAM,OAAO,GACX,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACxD,MAAM,OAAO,GACX,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACxD,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,OAAO,GAAG,OAAO,CAAA;IACjD,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAC3C,OAAO,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;AACzC,CAAC,CAAC,CAAA;AAEJ;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,WAAwB,EACxB,OAAgC,EACvB,EAAE;IACX,wCAAwC;IACxC,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QAE5C,0BAA0B;QAC1B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACnC,IAAI,CAAC,KAAK,EAAE,MAAM;YAAE,SAAQ;QAE5B,kEAAkE;QAClE,IAAI,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,WAAwB,EACxB,OAAgC,EAChC,QAAc,EACd,QAAmB,EACV,EAAE;IACX,gEAAgE;IAChE,yDAAyD;IACzD,6DAA6D;IAC7D,+CAA+C;IAC/C,IAAI,yBAAyB,CAAC,WAAW,EAAE,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAEhE,6DAA6D;IAC7D,KAAK,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QACxD,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QAE5C,2CAA2C;QAC3C,IAAI,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG;gBACN,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;gBACtB,MAAM;gBACN,IAAI;gBACJ,iBAAiB,EAAE,IAAI,GAAG,EAAE;aAC7B,CAAA;YACD,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;YAC5B,IAAI,SAAS;gBAAE,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACrD,SAAQ;QACV,CAAC;QAED,6DAA6D;QAC7D,gEAAgE;QAChE,8DAA8D;QAC9D,IAAI,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QAE/C,IACE,MAAM;YACN,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CACzB,SAAS,CACP,MAAM,CAAC,EAAE,EACT,CAAC,EACD,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,WAAW,EACpB,QAAQ,CACT,CACF,EACD,CAAC;YACD,IACE,MAAM,CAAC,EAAE,KAAK,KAAK,CAAC,MAAM,EAAE,EAAE;gBAC9B,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,EACxC,CAAC;gBACD,4DAA4D;gBAC5D,6DAA6D;gBAC7D,2DAA2D;gBAC3D,2CAA2C;gBAC3C,MAAM,8BAA8B,GAClC,KAAK,CAAC,MAAM;oBACZ,SAAS,CACP,KAAK,CAAC,MAAM,CAAC,EAAE,EACf,IAAI,EACJ,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,WAAW,EACpB,QAAQ,CACT,CAAA;gBAEH,IAAI,CAAC,8BAA8B,EAAE,CAAC;oBACpC,2DAA2D;oBAC3D,mDAAmD;oBACnD,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;wBACjD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;wBAC1C,IAAI,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;4BACnC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;4BAC5B,IAAI,CAAC,EAAE,GAAG,MAAM,CAAA;4BAChB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;wBAC1B,CAAC;oBACH,CAAC;oBACD,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;gBACvB,CAAC;YACH,CAAC;YAED,kDAAkD;YAClD,KAAK,CAAC,MAAM,KAAK,MAAM,CAAA;QACzB,CAAC;QAED,qCAAqC;QACrC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACrB,IAAI,SAAS;YAAE,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACvD,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,KAAY,EACZ,WAAwB,EACxB,OAAgC,EACnB,EAAE;IACf,gCAAgC;IAChC,MAAM,eAAe,GAAgB,IAAI,GAAG,EAAE,CAAA;IAC9C,eAAe,CAAC,KAAK,GAAG,KAAK,CAAC,oBAAoB,EAAE,CAAA;IACpD,2BAA2B;IAC3B,KAAK,CAAC,YAAY,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,eAAe,CAAA;IAE3D,sEAAsE;IACtE,2EAA2E;IAC3E,8DAA8D;IAC9D,6EAA6E;IAC7E,2EAA2E;IAC3E,2EAA2E;IAC3E,iFAAiF;IACjF,qCAAqC;IACrC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE;YACxB,MAAM,EAAE,KAAK;YACb,KAAK,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;YAC3B,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,iBAAiB,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC;SACpD,CAAC,CAAA;IACJ,CAAC;IAED,uEAAuE;IACvE,6EAA6E;IAC7E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAA;QAC/C,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QAEjE,4EAA4E;QAC5E,6EAA6E;QAC7E,4EAA4E;QAC5E,6EAA6E;QAC7E,kEAAkE;QAClE,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC/C,MAAM,eAAe,GACnB,CAAC,MAAM,IAAI,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;QAElE,MAAM,QAAQ,GAAG;YACf,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YACtB,MAAM,EAAE,eAAe;YACvB,IAAI;YACJ,iBAAiB,EACf,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAQ;SACrD,CAAA;QACD,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACrC,CAAC;IAED,OAAO,eAAe,CAAA;AACxB,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,WAAwB,EACxB,QAAkB,EAClB,QAAc,EACd,OAAoB,EACpB,EAAE;IACF,sEAAsE;IACtE,mEAAmE;IACnE,6CAA6C;IAC7C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiC,CAAA;IACzD,IAAI,WAA+B,CAAA;IAEnC,IACE,QAAQ,CAAC,gBAAgB;QACzB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC,EACjD,CAAC;QACD,mDAAmD;QACnD,wCAAwC;QACxC,WAAW,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAA;QAElD,gDAAgD;QAChD,kDAAkD;QAClD,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,EAAE;YAC5C,GAAG,OAAO;YACV,QAAQ,EAAE,QAAQ,CAAC,QAAQ;SAC5B,CAAC,CAAA;QACF,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;YACzC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;QAC5B,CAAC;QAED,wDAAwD;QACxD,sDAAsD;QACtD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;gBACtB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW;QACX,6CAA6C;QAC7C,aAAa,EAAE,4BAA4B,CAAC;YAC1C,GAAG,QAAQ,CAAC,MAAM,EAAE;SACrB,CAAC;KACH,CAAA;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,WAAwB,EACxB,QAAsB,EACtB,YAAuD,EACvD,KAAY,EACZ,IAAU,EACV,QAAc,EACd,IAAU,EACV,IAAwB,EACxB,aAAsC,EACtC,EAAE,CAAC,CAAC;IACJ;;OAEG;IACH,UAAU,EAAE,GAAG,EAAE;QACf,qEAAqE;QACrE,IAAI,sBAAsB,GAAG,KAAK,CAAA;QAClC,kDAAkD;QAClD,kDAAkD;QAClD,MAAM,WAAW,GAAG;YAClB,GAAG,aAAa;YAChB,gBAAgB,CAAC;gBACf,IAAI;gBACJ,MAAM,EAAE,IAAI;gBACZ,IAAI;aACL;SACF,CAAA;QACD,uBAAuB,CACrB,WAAW,EACX,WAAW,EACX,QAAQ,EACR,KAAK,CAAC,QAAQ,CACf,CAAA;QAED,2CAA2C;QAC3C,MAAM,WAAW,GAAG;YAClB,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,GAAG,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxC,GAAG,GAAG;gBACN,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;SACJ,CAAA;QACD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,sBAAsB,GAAG,uBAAuB,CAC9C,WAAW,EACX,WAAW,EACX,IAAI,EACJ,KAAK,CAAC,QAAQ,CACf,CAAA;QACH,CAAC;QAED,wDAAwD;QACxD,mEAAmE;QACnE,OAAO,sBAAsB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAA;IACzD,CAAC;IAED;;;;OAIG;IACH,eAAe,EAAE,CAAC,cAA2B,EAAE,EAAE;QAC/C,8DAA8D;QAC9D,8DAA8D;QAC9D,oEAAoE;QACpE,+DAA+D;QAC/D,kDAAkD;QAClD,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;YAC9B,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;gBAC/C,+DAA+D;gBAC/D,+DAA+D;gBAC/D,4DAA4D;gBAC5D,gEAAgE;gBAChE,wDAAwD;gBACxD,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CACrC,CAAC,CAAC,EAAE,CACF,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAC5D,CAAA;gBAED,IACE,YAAY,EAAE,MAAM;oBACpB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;oBACnC,SAAS,CACP,YAAY,CAAC,MAAM,CAAC,EAAE,EACtB,IAAI,EACJ,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,WAAW,EACpB,KAAK,CAAC,QAAQ,CACf,EACD,CAAC;oBACD,yDAAyD;oBACzD,yDAAyD;oBACzD,wDAAwD;oBACxD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAA;oBACpD,SAAQ;gBACV,CAAC;gBAED,wDAAwD;gBACxD,4DAA4D;gBAC5D,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;gBACjD,IACE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;oBACnC,KAAK,EAAE,MAAM;oBACb,SAAS,CACP,KAAK,CAAC,MAAM,CAAC,EAAE,EACf,IAAI,EACJ,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,WAAW,EACpB,KAAK,CAAC,QAAQ,CACf,EACD,CAAC;oBACD,4CAA4C;oBAC5C,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;oBAC7C,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC7B,CAAC;qBAAM,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;oBACnC,8CAA8C;oBAC9C,8BAA8B;oBAC9B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;gBACjC,CAAC;qBAAM,IACL,YAAY;oBACZ,YAAY,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,EAC5C,CAAC;oBACD,qDAAqD;oBACrD,2DAA2D;oBAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,CAAA;gBACxD,CAAC;qBAAM,CAAC;oBACN,mEAAmE;oBACnE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,KAAY,EACZ,kBAA4C,EAC5C,EAAE;IACF,qEAAqE;IACrE,qEAAqE;IACrE,4BAA4B;IAC5B,KAAK,MAAM,kBAAkB,IAAI,kBAAkB,EAAE,CAAC;QACpD,uDAAuD;QACvD,MAAM,eAAe,GAAG,CAAC,GAAG,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC5D,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CACzC,CAAA;QAED,MAAM,YAAY,GAAG,IAAI,GAAG,EAOzB,CAAA;QACH,iEAAiE;QACjE,iEAAiE;QACjE,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACvC,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,EAAE,CAAA;YACrD,IAAI,SAAS,EAAE,CAAC;gBACd,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;YACvC,CAAC;QACH,CAAC;QAED,qFAAqF;QACrF,MAAM,yBAAyB,GAAG;YAChC,GAAG,YAAY,CAAC,OAAO,EAAE;SAC1B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAA;QAE9D,iEAAiE;QACjE,wDAAwD;QACxD,IAAI,WAAW,CAAA;QACf,KAAK,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,IAAI,yBAAyB,EAAE,CAAC;YAChE,IACE,WAAW;gBACX,CAAC,yBAAyB,CAAC,WAAW,EAAE,WAAW,CAAC,EACpD,CAAC;gBACD,oDAAoD;gBACpD,uBAAuB,CACrB,WAAW,EACX,WAAW,EACX,QAAQ,CAAC,IAAI,EACb,KAAK,CAAC,QAAQ,CACf,CAAA;gBACD,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAA;gBAClC,SAAQ;YACV,CAAC;YACD,QAAQ,CAAC,WAAW,GAAG,eAAe,CACpC,KAAK,EACL,QAAQ,CAAC,WAAW,EACpB,WAAW,CACZ,CAAA;YACD,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;QACpC,CAAC;QACD,4CAA4C;QAC5C,8BAA8B;QAC9B,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACvC,4DAA4D;YAC5D,qEAAqE;YACrE,QAAQ,CAAC,aAAa,CAAC,eAAe,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;YAC5D,QAAQ,CAAC,IAAI,GAAG,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACvD,CAAC;IACH,CAAC;AACH,CAAC,CAAA","sourcesContent":["// helpers for managing peer dependency resolution\n// during the ideal graph building process.\n\nimport { intersects } from '@vltpkg/semver'\nimport { satisfies } from '@vltpkg/satisfies'\nimport { getDependencies } from '../dependencies.ts'\nimport { getOrderedDependencies } from './get-ordered-dependencies.ts'\nimport type {\n ProcessPlacementResultEntry,\n PeerContext,\n PeerContextEntry,\n PeerContextEntryInput,\n ProcessPlacementResult,\n} from './types.ts'\nimport type { Spec, SpecOptions } from '@vltpkg/spec'\nimport type { DependencySaveType, Manifest } from '@vltpkg/types'\nimport type { Monorepo } from '@vltpkg/workspaces'\nimport type { Dependency } from '../dependencies.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\n\n/**\n * Retrieve a unique hash value for a given peer context set.\n */\nexport const retrievePeerContextHash = (\n peerContext: PeerContext | undefined,\n): string | undefined => {\n // skips creating the initial peer context ref\n if (!peerContext?.index) return undefined\n\n return `ṗ:${peerContext.index}`\n}\n\n/**\n * Checks if a given spec is compatible with the specs already\n * assigned to a peer context entry.\n *\n * Returns true if compatible, false otherwise.\n */\nexport const incompatibleSpecs = (\n spec: Spec,\n entry: PeerContextEntry,\n): boolean => {\n if (entry.specs.size > 0) {\n for (const s of entry.specs) {\n if (\n // only able to check range intersections for registry types\n (spec.type === 'registry' &&\n (!spec.range ||\n !s.range ||\n !intersects(spec.range, s.range))) ||\n // also support types other than registry in case\n // they use the very same bareSpec value\n (spec.type !== 'registry' && spec.bareSpec !== s.bareSpec)\n ) {\n return true\n }\n }\n }\n return false\n}\n\n/**\n * Sort peer context entry inputs for deterministic processing.\n * Orders: non-peer dependencies first, then peer dependencies, alphabetically by name.\n */\nexport const getOrderedPeerContextEntries = (\n entries: PeerContextEntryInput[],\n): PeerContextEntryInput[] =>\n [...entries].sort((a, b) => {\n const aIsPeer =\n a.type === 'peer' || a.type === 'peerOptional' ? 1 : 0\n const bIsPeer =\n b.type === 'peer' || b.type === 'peerOptional' ? 1 : 0\n if (aIsPeer !== bIsPeer) return aIsPeer - bIsPeer\n const aName = a.target?.name ?? a.spec.name\n const bName = b.target?.name ?? b.spec.name\n return aName.localeCompare(bName, 'en')\n })\n\n/*\n * Checks if there are any conflicting versions for a given dependency\n * to be added to a peer context set which will require forking.\n *\n * Returns true if forking is needed, false otherwise.\n */\nexport const checkEntriesToPeerContext = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n): boolean => {\n // check on compatibility of new entries\n for (const { spec, target } of entries) {\n const name = target?.name ?? spec.final.name\n\n // skip any inactive entry\n const entry = peerContext.get(name)\n if (!entry?.active) continue\n\n // validate if the provided spec is compatible with existing specs\n if (incompatibleSpecs(spec, entry)) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Add or update dependencies in a given peer context making sure to check\n * for compatibility with existing dependencies already resolved by a given\n * peer context set. Extra info such as a target or dependent nodes is\n * optional.\n *\n * Returns true if forking is needed, false otherwise.\n */\nexport const addEntriesToPeerContext = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n fromNode: Node,\n monorepo?: Monorepo,\n): boolean => {\n // pre check to see if any of the new entries to be added to the\n // provided peer context set conflicts with existing ones\n // if that's already the case we can skip processing them and\n // will return that a fork is needed right away\n if (checkEntriesToPeerContext(peerContext, entries)) return true\n\n // iterate on every entry to be added to the peer context set\n for (const { dependent, spec, target, type } of entries) {\n const name = target?.name ?? spec.final.name\n\n // if there's no existing entry, create one\n let entry = peerContext.get(name)\n if (!entry) {\n entry = {\n active: true,\n specs: new Set([spec]),\n target,\n type,\n contextDependents: new Set(),\n }\n peerContext.set(name, entry)\n if (dependent) entry.contextDependents.add(dependent)\n continue\n }\n\n // perform an extra check that confirms the new spec does not\n // conflicts with existing specs in this entry, this handles the\n // case of adding sibling deps that conflicts with one another\n if (incompatibleSpecs(spec, entry)) return true\n\n if (\n target &&\n [...entry.specs].every(s =>\n satisfies(\n target.id,\n s,\n fromNode.location,\n fromNode.projectRoot,\n monorepo,\n ),\n )\n ) {\n if (\n target.id !== entry.target?.id &&\n target.version !== entry.target?.version\n ) {\n // Check if the existing target also satisfies the new spec.\n // If it does, we should keep the existing target rather than\n // switching to the new one. This preserves pinned versions\n // and prevents unnecessary target changes.\n const existingTargetSatisfiesNewSpec =\n entry.target &&\n satisfies(\n entry.target.id,\n spec,\n fromNode.location,\n fromNode.projectRoot,\n monorepo,\n )\n\n if (!existingTargetSatisfiesNewSpec) {\n // Only update all dependents to point to the new target if\n // the existing target doesn't satisfy the new spec\n for (const dependents of entry.contextDependents) {\n const edge = dependents.edgesOut.get(name)\n if (edge?.to && edge.to !== target) {\n edge.to.edgesIn.delete(edge)\n edge.to = target\n target.edgesIn.add(edge)\n }\n }\n entry.target = target\n }\n }\n\n // otherwise sets the value in case it was nullish\n entry.target ??= target\n }\n\n // update specs and dependents values\n entry.specs.add(spec)\n if (dependent) entry.contextDependents.add(dependent)\n }\n\n return false\n}\n\n/**\n * Create and returns a forked copy of a given peer context set.\n */\nexport const forkPeerContext = (\n graph: Graph,\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n): PeerContext => {\n // create a new peer context set\n const nextPeerContext: PeerContext = new Map()\n nextPeerContext.index = graph.nextPeerContextIndex()\n // register it in the graph\n graph.peerContexts[nextPeerContext.index] = nextPeerContext\n\n // copy existing entries marking them as inactive, it's also important\n // to note that specs and contextDependents are new objects so that changes\n // to those in the new context do not affect the previous one.\n // IMPORTANT: We preserve the target from the parent context so that packages\n // in the forked context can still resolve peer deps to the same version as\n // the parent context. This fixes an issue where forked contexts would lose\n // track of already-resolved peer dependencies (like a pinned typescript version)\n // and resolve to different versions.\n for (const [name, entry] of peerContext.entries()) {\n nextPeerContext.set(name, {\n active: false,\n specs: new Set(entry.specs),\n target: entry.target,\n type: entry.type,\n contextDependents: new Set(entry.contextDependents),\n })\n }\n\n // add the new entries to this peer context set, marking them as active\n // these are the entries that were incompatible with the previous context set\n for (const entry of entries) {\n const { dependent, spec, target, type } = entry\n const name = target?.name /* c8 ignore next */ ?? spec.final.name\n\n // IMPORTANT: If the new entry has no target but the parent context had one,\n // preserve the parent's target. This ensures that when a fork happens due to\n // spec \"incompatibility\" (e.g., pinned version vs range), we don't lose the\n // already-resolved target. The satisfies check in resolvePeerDeps will later\n // verify if the preserved target actually satisfies the new spec.\n const existingEntry = nextPeerContext.get(name)\n const preservedTarget =\n !target && existingEntry?.target ? existingEntry.target : target\n\n const newEntry = {\n active: true,\n specs: new Set([spec]),\n target: preservedTarget,\n type,\n contextDependents:\n dependent ? new Set([dependent]) : new Set<Node>(),\n }\n nextPeerContext.set(name, newEntry)\n }\n\n return nextPeerContext\n}\n\n/**\n * Starts the peer dependency placement process\n * for a given node being processed and placed.\n */\nexport const startPeerPlacement = (\n peerContext: PeerContext,\n manifest: Manifest,\n fromNode: Node,\n options: SpecOptions,\n) => {\n // queue entries so that they can be added at the end of the placement\n // process, use a map to ensure deduplication between read json dep\n // values and the resolved edges in the graph\n const queueMap = new Map<string, PeerContextEntryInput>()\n let peerSetHash: string | undefined\n\n if (\n manifest.peerDependencies &&\n Object.keys(manifest.peerDependencies).length > 0\n ) {\n // generates a peer context set hash for nodes that\n // have peer dependencies to be resolved\n peerSetHash = retrievePeerContextHash(peerContext)\n\n // get any potential sibling dependency from the\n // parent node that might have not been parsed yet\n const siblingDeps = getDependencies(fromNode, {\n ...options,\n registry: fromNode.registry,\n })\n for (const [depName, dep] of siblingDeps) {\n queueMap.set(depName, dep)\n }\n\n // collect the already parsed nodes and add those to the\n // list of entries to be added to the peer context set\n for (const edge of fromNode.edgesOut.values()) {\n queueMap.set(edge.name, {\n spec: edge.spec,\n target: edge.to,\n type: edge.type,\n })\n }\n }\n\n return {\n peerSetHash,\n // Sort queuedEntries for deterministic order\n queuedEntries: getOrderedPeerContextEntries([\n ...queueMap.values(),\n ]),\n }\n}\n\n/**\n * Ends the peer dependency placement process, returning the functions that\n * are going to be used to update the peer context set, forking when needed\n * and resolving peer dependencies if possible.\n */\nexport const endPeerPlacement = (\n peerContext: PeerContext,\n nextDeps: Dependency[],\n nextPeerDeps: Map<string, Dependency> & { id?: number },\n graph: Graph,\n spec: Spec,\n fromNode: Node,\n node: Node,\n type: DependencySaveType,\n queuedEntries: PeerContextEntryInput[],\n) => ({\n /**\n * Add the new entries to the current peer context set.\n */\n putEntries: () => {\n // keep track of whether we need to fork the current peer context set\n let needsToForkPeerContext = false\n // add queued entries from this node parents along\n // with a self-ref to the current peer context set\n const prevEntries = [\n ...queuedEntries,\n /* ref itself */ {\n spec,\n target: node,\n type,\n },\n ]\n addEntriesToPeerContext(\n peerContext,\n prevEntries,\n fromNode,\n graph.monorepo,\n )\n\n // add this node's direct dependencies next\n const nextEntries = [\n ...nextDeps.map(dep => ({ ...dep, dependent: node })),\n ...[...nextPeerDeps.values()].map(dep => ({\n ...dep,\n dependent: node,\n })),\n ]\n if (nextEntries.length > 0) {\n needsToForkPeerContext = addEntriesToPeerContext(\n peerContext,\n nextEntries,\n node,\n graph.monorepo,\n )\n }\n\n // returns all entries that need to be added to a forked\n // context or undefined if the current context was updated directly\n return needsToForkPeerContext ? nextEntries : undefined\n },\n\n /**\n * Try to resolve peer dependencies using already seen target\n * values from the current peer context set.\n * @param {PeerContext} currentContext The current peer context (may be forked from original)\n */\n resolvePeerDeps: (currentContext: PeerContext) => {\n // iterate on the set of peer dependencies of the current node\n // and try to resolve them from the existing peer context set,\n // when possible, add them as edges in the graph right away, if not,\n // then we move them back to the `nextDeps` list for processing\n // along with the rest of the regular dependencies\n for (const nextDep of nextPeerDeps.values()) {\n const { spec, type } = nextDep\n if (type === 'peer' || type === 'peerOptional') {\n // FIRST: Check if there's a sibling dependency from the parent\n // that specifies this same package. Sibling deps take priority\n // because they represent the workspace's direct dependency,\n // which should be preferred over versions from other workspaces\n // that may have been added to the peer context earlier.\n const siblingEntry = queuedEntries.find(\n e =>\n (e.target?.name ?? e.spec.final.name) === spec.final.name,\n )\n\n if (\n siblingEntry?.target &&\n !node.edgesOut.has(spec.final.name) &&\n satisfies(\n siblingEntry.target.id,\n spec,\n fromNode.location,\n fromNode.projectRoot,\n graph.monorepo,\n )\n ) {\n // The sibling's resolved target satisfies the peer spec,\n // use it directly - this prioritizes the workspace's own\n // direct dependency over versions from other workspaces\n graph.addEdge(type, spec, node, siblingEntry.target)\n continue\n }\n\n // THEN: Try to retrieve an entry for that peer dep from\n // the current peer context set (which may have been forked)\n const entry = currentContext.get(spec.final.name)\n if (\n !node.edgesOut.has(spec.final.name) &&\n entry?.target &&\n satisfies(\n entry.target.id,\n spec,\n fromNode.location,\n fromNode.projectRoot,\n graph.monorepo,\n )\n ) {\n // entry satisfied, create edge in the graph\n graph.addEdge(type, spec, node, entry.target)\n entry.specs.add(spec.final)\n } else if (type === 'peerOptional') {\n // skip unsatisfied peerOptional dependencies,\n // just create a dangling edge\n graph.addEdge(type, spec, node)\n } else if (\n siblingEntry &&\n siblingEntry.spec.bareSpec !== spec.bareSpec\n ) {\n // Sibling has a more specific spec for this package,\n // use it when resolving to ensure we get the right version\n nextDeps.push({ ...nextDep, spec: siblingEntry.spec })\n } else {\n // could not satisfy from peer context or sibling, add to next deps\n nextDeps.push(nextDep)\n }\n }\n }\n },\n})\n\n/**\n * Given an array of processed results for the current level dependencies\n * being placed in the currently building ideal graph, traverse its direct\n * dependencies and track peer dependencies in their appropriate peer context\n * sets, forking as needed and resolving peer dependencies using suitable\n * nodes already present in the graph if possible.\n */\nexport const postPlacementPeerCheck = (\n graph: Graph,\n sortedLevelResults: ProcessPlacementResult[],\n) => {\n // Update peer contexts in a sorted manner after processing all nodes\n // at a given level to ensure deterministic behavior when it comes to\n // forking new peer contexts\n for (const childDepsToProcess of sortedLevelResults) {\n // Sort childDepsToProcess deterministically by node.id\n const sortedChildDeps = [...childDepsToProcess].sort((a, b) =>\n a.node.id.localeCompare(b.node.id, 'en'),\n )\n\n const needsForking = new Map<\n ProcessPlacementResultEntry,\n {\n dependent: Node\n spec: Spec\n type: DependencySaveType\n }[]\n >()\n // first iterate on all child deps, adding entries to the current\n // context and collect the information on which ones need forking\n for (const childDep of sortedChildDeps) {\n const needsFork = childDep.updateContext.putEntries()\n if (needsFork) {\n needsForking.set(childDep, needsFork)\n }\n }\n\n // Sort needsForking entries before iterating (Map iteration order = insertion order)\n const sortedNeedsForkingEntries = [\n ...needsForking.entries(),\n ].sort(([a], [b]) => a.node.id.localeCompare(b.node.id, 'en'))\n\n // then iterate again, forking contexts as needed but also try to\n // reuse the context of the previous sibling if possible\n let prevContext\n for (const [childDep, nextEntries] of sortedNeedsForkingEntries) {\n if (\n prevContext &&\n !checkEntriesToPeerContext(prevContext, nextEntries)\n ) {\n // the context of the previous sibling can be reused\n addEntriesToPeerContext(\n prevContext,\n nextEntries,\n childDep.node,\n graph.monorepo,\n )\n childDep.peerContext = prevContext\n continue\n }\n childDep.peerContext = forkPeerContext(\n graph,\n childDep.peerContext,\n nextEntries,\n )\n prevContext = childDep.peerContext\n }\n // try to resolve peer dependencies now that\n // the context is fully set up\n for (const childDep of sortedChildDeps) {\n // Pass the current peerContext (which may have been forked)\n // so resolvePeerDeps uses the correct context with preserved targets\n childDep.updateContext.resolvePeerDeps(childDep.peerContext)\n childDep.deps = getOrderedDependencies(childDep.deps)\n }\n }\n}\n"]}
@@ -64,7 +64,7 @@ export type AppendNodeEntry = {
64
64
  spec: Spec;
65
65
  type: DependencySaveType;
66
66
  }[] | undefined;
67
- resolvePeerDeps: () => void;
67
+ resolvePeerDeps: (currentContext: PeerContext) => void;
68
68
  };
69
69
  };
70
70
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ideal/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,KAAK,EACV,2BAA2B,EAC3B,UAAU,EACV,8BAA8B,EAC/B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,2BAA2B,EAC3B,sBAAsB,CACvB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,8BAA8B,EAC9B,sBAAsB,CACvB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;OAKG;IACH,GAAG,EAAE,2BAA2B,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;;;OAKG;IACH,MAAM,EAAE,8BAA8B,CAAA;CACvC,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC;;;OAGG;IACH,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,WAAW,EAAE,iBAAiB,CAAA;CAC/B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,EAAE,UAAU,EAAE,CAAA;IAClB,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAC/C,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,WAAW,CAAA;IACxB,aAAa,EAAE;QACb,UAAU,EAAE,MACR;YACE,SAAS,EAAE,IAAI,CAAA;YACf,IAAI,EAAE,IAAI,CAAA;YACV,IAAI,EAAE,kBAAkB,CAAA;SACzB,EAAE,GACH,SAAS,CAAA;QACb,eAAe,EAAE,MAAM,IAAI,CAAA;KAC5B,CAAA;CACF,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,eAAe,EACf,OAAO,CACR,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,2BAA2B,EAAE,CAAA;AAElE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAA;IACf,yEAAyE;IACzE,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;IAChB,2EAA2E;IAC3E,MAAM,EAAE,IAAI,GAAG,SAAS,CAAA;IACxB,mDAAmD;IACnD,IAAI,EAAE,kBAAkB,CAAA;IACxB,2EAA2E;IAC3E,iBAAiB,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;CAC7B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,gEAAgE;IAChE,SAAS,CAAC,EAAE,IAAI,CAAA;IAChB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,IAAI,CAAA;CACd,GAAG,UAAU,CAAA;AAEd;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG;IACxD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ideal/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,KAAK,EACV,2BAA2B,EAC3B,UAAU,EACV,8BAA8B,EAC/B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,2BAA2B,EAC3B,sBAAsB,CACvB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,8BAA8B,EAC9B,sBAAsB,CACvB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;OAKG;IACH,GAAG,EAAE,2BAA2B,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;;;OAKG;IACH,MAAM,EAAE,8BAA8B,CAAA;CACvC,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC;;;OAGG;IACH,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,WAAW,EAAE,iBAAiB,CAAA;CAC/B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,EAAE,UAAU,EAAE,CAAA;IAClB,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAC/C,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,WAAW,CAAA;IACxB,aAAa,EAAE;QACb,UAAU,EAAE,MACR;YACE,SAAS,EAAE,IAAI,CAAA;YACf,IAAI,EAAE,IAAI,CAAA;YACV,IAAI,EAAE,kBAAkB,CAAA;SACzB,EAAE,GACH,SAAS,CAAA;QACb,eAAe,EAAE,CAAC,cAAc,EAAE,WAAW,KAAK,IAAI,CAAA;KACvD,CAAA;CACF,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,eAAe,EACf,OAAO,CACR,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,2BAA2B,EAAE,CAAA;AAElE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAA;IACf,yEAAyE;IACzE,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;IAChB,2EAA2E;IAC3E,MAAM,EAAE,IAAI,GAAG,SAAS,CAAA;IACxB,mDAAmD;IACnD,IAAI,EAAE,kBAAkB,CAAA;IACxB,2EAA2E;IAC3E,iBAAiB,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;CAC7B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,gEAAgE;IAChE,SAAS,CAAC,EAAE,IAAI,CAAA;IAChB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,IAAI,CAAA;CACd,GAAG,UAAU,CAAA;AAEd;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG;IACxD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ideal/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DepID } from '@vltpkg/dep-id'\nimport type { PackageInfoClient } from '@vltpkg/package-info'\nimport type { Spec } from '@vltpkg/spec'\nimport type { DependencySaveType } from '@vltpkg/types'\nimport type {\n AddImportersDependenciesMap,\n Dependency,\n RemoveImportersDependenciesMap,\n} from '../dependencies.ts'\nimport type { ModifierActiveEntry } from '../modifiers.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\n\n/**\n * A map of dependencies to be added to non-importer nodes.\n * Keys are {@link DepID} of nodes that are not importers (e.g., nested folders).\n * When these nodes are resolved and placed in the graph, their dependencies\n * from this map are injected into the processing queue.\n */\nexport type TransientAddMap = Omit<\n AddImportersDependenciesMap,\n 'modifiedDependencies'\n>\n\n/**\n * A map of dependency names to be removed from non-importer nodes.\n * Keys are {@link DepID} of nodes that are not importers (e.g., nested folders).\n * When these nodes are processed, their dependencies in this map are excluded.\n */\nexport type TransientRemoveMap = Omit<\n RemoveImportersDependenciesMap,\n 'modifiedDependencies'\n>\n\nexport type BuildIdealAddOptions = {\n /**\n * A {@link AddImportersDependenciesMap} in which keys are {@link DepID}\n * linking to another `Map` in which keys are the dependency names and values\n * are {@link Dependency}. This structure represents dependencies that need\n * to be added to the importer represented by {@link DepID}.\n */\n add: AddImportersDependenciesMap\n}\n\nexport type BuildIdealRemoveOptions = {\n /**\n * A {@link RemoveImportersDependenciesMap} object representing nodes to be\n * removed from the ideal graph. Each {@link DepID} key represents an\n * importer node and the `Set` of dependency names to be removed from its\n * dependency list.\n */\n remove: RemoveImportersDependenciesMap\n}\n\nexport type BuildIdealFromGraphOptions = {\n /**\n * An initial {@link Graph} to start building from, adding nodes to any\n * missing edges and appending any new specs defined in `addSpecs`.\n */\n graph: Graph\n}\n\nexport type BuildIdealPackageInfoOptions = {\n /**\n * A {@link PackageInfoClient} instance to read manifest info from.\n */\n packageInfo: PackageInfoClient\n}\n\n/**\n * Represents an ongoing append operation for a node and its dependencies.\n */\nexport type AppendNodeEntry = {\n node: Node\n deps: Dependency[]\n modifierRefs?: Map<string, ModifierActiveEntry>\n depth: number\n peerContext: PeerContext\n updateContext: {\n putEntries: () =>\n | {\n dependent: Node\n spec: Spec\n type: DependencySaveType\n }[]\n | undefined\n resolvePeerDeps: () => void\n }\n}\n\n/**\n * The result of processing a given placed node in the graph.\n */\nexport type ProcessPlacementResultEntry = Omit<\n AppendNodeEntry,\n 'depth'\n>\n\n/**\n * The result of processing placement for nodes to be added to the graph.\n */\nexport type ProcessPlacementResult = ProcessPlacementResultEntry[]\n\n/**\n * Entry in a peer context representing a resolved peer dependency.\n */\nexport type PeerContextEntry = {\n /**\n * True if this entry is currently being resolved and track by this\n * peer context set, false in case this entry was inherit from a previous\n * peer context set and should not be considered for resolution.\n */\n active: boolean\n /** List of full Spec objects that are part of this peer context entry */\n specs: Set<Spec>\n /** The target Node that satisfies all specs for this peer context entry */\n target: Node | undefined\n /** The type of dependency this entry represents */\n type: DependencySaveType\n /** Context dependent nodes that had dependencies resolved to this entry */\n contextDependents: Set<Node>\n}\n\n/**\n * Input for adding an entry to peer contexts.\n */\nexport type PeerContextEntryInput = {\n /** Node that depends on this resolved peer context set entry */\n dependent?: Node\n /** Node this peer context entry resolves to */\n target?: Node\n} & Dependency\n\n/**\n * Represents resolved peer dependencies in a given append-nodes context.\n */\nexport type PeerContext = Map<string, PeerContextEntry> & {\n index?: number\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ideal/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DepID } from '@vltpkg/dep-id'\nimport type { PackageInfoClient } from '@vltpkg/package-info'\nimport type { Spec } from '@vltpkg/spec'\nimport type { DependencySaveType } from '@vltpkg/types'\nimport type {\n AddImportersDependenciesMap,\n Dependency,\n RemoveImportersDependenciesMap,\n} from '../dependencies.ts'\nimport type { ModifierActiveEntry } from '../modifiers.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\n\n/**\n * A map of dependencies to be added to non-importer nodes.\n * Keys are {@link DepID} of nodes that are not importers (e.g., nested folders).\n * When these nodes are resolved and placed in the graph, their dependencies\n * from this map are injected into the processing queue.\n */\nexport type TransientAddMap = Omit<\n AddImportersDependenciesMap,\n 'modifiedDependencies'\n>\n\n/**\n * A map of dependency names to be removed from non-importer nodes.\n * Keys are {@link DepID} of nodes that are not importers (e.g., nested folders).\n * When these nodes are processed, their dependencies in this map are excluded.\n */\nexport type TransientRemoveMap = Omit<\n RemoveImportersDependenciesMap,\n 'modifiedDependencies'\n>\n\nexport type BuildIdealAddOptions = {\n /**\n * A {@link AddImportersDependenciesMap} in which keys are {@link DepID}\n * linking to another `Map` in which keys are the dependency names and values\n * are {@link Dependency}. This structure represents dependencies that need\n * to be added to the importer represented by {@link DepID}.\n */\n add: AddImportersDependenciesMap\n}\n\nexport type BuildIdealRemoveOptions = {\n /**\n * A {@link RemoveImportersDependenciesMap} object representing nodes to be\n * removed from the ideal graph. Each {@link DepID} key represents an\n * importer node and the `Set` of dependency names to be removed from its\n * dependency list.\n */\n remove: RemoveImportersDependenciesMap\n}\n\nexport type BuildIdealFromGraphOptions = {\n /**\n * An initial {@link Graph} to start building from, adding nodes to any\n * missing edges and appending any new specs defined in `addSpecs`.\n */\n graph: Graph\n}\n\nexport type BuildIdealPackageInfoOptions = {\n /**\n * A {@link PackageInfoClient} instance to read manifest info from.\n */\n packageInfo: PackageInfoClient\n}\n\n/**\n * Represents an ongoing append operation for a node and its dependencies.\n */\nexport type AppendNodeEntry = {\n node: Node\n deps: Dependency[]\n modifierRefs?: Map<string, ModifierActiveEntry>\n depth: number\n peerContext: PeerContext\n updateContext: {\n putEntries: () =>\n | {\n dependent: Node\n spec: Spec\n type: DependencySaveType\n }[]\n | undefined\n resolvePeerDeps: (currentContext: PeerContext) => void\n }\n}\n\n/**\n * The result of processing a given placed node in the graph.\n */\nexport type ProcessPlacementResultEntry = Omit<\n AppendNodeEntry,\n 'depth'\n>\n\n/**\n * The result of processing placement for nodes to be added to the graph.\n */\nexport type ProcessPlacementResult = ProcessPlacementResultEntry[]\n\n/**\n * Entry in a peer context representing a resolved peer dependency.\n */\nexport type PeerContextEntry = {\n /**\n * True if this entry is currently being resolved and track by this\n * peer context set, false in case this entry was inherit from a previous\n * peer context set and should not be considered for resolution.\n */\n active: boolean\n /** List of full Spec objects that are part of this peer context entry */\n specs: Set<Spec>\n /** The target Node that satisfies all specs for this peer context entry */\n target: Node | undefined\n /** The type of dependency this entry represents */\n type: DependencySaveType\n /** Context dependent nodes that had dependencies resolved to this entry */\n contextDependents: Set<Node>\n}\n\n/**\n * Input for adding an entry to peer contexts.\n */\nexport type PeerContextEntryInput = {\n /** Node that depends on this resolved peer context set entry */\n dependent?: Node\n /** Node this peer context entry resolves to */\n target?: Node\n} & Dependency\n\n/**\n * Represents resolved peer dependencies in a given append-nodes context.\n */\nexport type PeerContext = Map<string, PeerContextEntry> & {\n index?: number\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/reify/build.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAKtC;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,IAAI,EAAE,CAAA;IACf,OAAO,EAAE,IAAI,EAAE,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,KAAK,SACV,IAAI,eACG,WAAW,UAChB,UAAU,qBACC,GAAG,CAAC,KAAK,CAAC,KAC5B,OAAO,CAAC,WAAW,CA6DrB,CAAA"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/reify/build.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAKtC;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,IAAI,EAAE,CAAA;IACf,OAAO,EAAE,IAAI,EAAE,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,KAAK,SACV,IAAI,eACG,WAAW,UAChB,UAAU,qBACC,GAAG,CAAC,KAAK,CAAC,KAC5B,OAAO,CAAC,WAAW,CA6DrB,CAAA"}
@@ -1,6 +1,7 @@
1
1
  // walk the graph of added nodes, building and chmoding their bins
2
2
  // at the end, we get back to the importers, and run their prepare
3
3
  // script as well as install script.
4
+ import { join } from 'node:path';
4
5
  import { run } from '@vltpkg/run';
5
6
  import { graphRun } from '@vltpkg/graph-run';
6
7
  import { nonEmptyList } from "../non-empty-list.js";
@@ -71,8 +72,16 @@ const visit = async (packageJson, scurry, node, signal, _path) => {
71
72
  const { manifest } = node;
72
73
  const { scripts = {} } = manifest;
73
74
  const { install, preinstall, postinstall, prepare, preprepare, postprepare, } = scripts;
74
- // if it has install script, run it
75
- const runInstall = !!(install || preinstall || postinstall);
75
+ // Check for binding.gyp file (npm's implicit install detection)
76
+ // "If there is a binding.gyp file in the root of your package and you
77
+ // haven't defined your own install or preinstall scripts, npm will default
78
+ // the install command to compile using node-gyp via node-gyp rebuild"
79
+ const hasBindingGyp = scurry
80
+ .lstatSync(join(node.resolvedLocation(scurry), 'binding.gyp'))
81
+ ?.isFile() ?? false;
82
+ const hasImplicitInstall = hasBindingGyp && !install && !preinstall;
83
+ // if it has install script or binding.gyp (implicit install), run it
84
+ const runInstall = !!(install || preinstall || postinstall) || hasImplicitInstall;
76
85
  if (runInstall) {
77
86
  await run({
78
87
  signal,
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/reify/build.ts"],"names":[],"mappings":"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","sourcesContent":["// walk the graph of added nodes, building and chmoding their bins\n// at the end, we get back to the importers, and run their prepare\n// script as well as install script.\n\nimport type { PackageJson } from '@vltpkg/package-json'\nimport { run } from '@vltpkg/run'\nimport { graphRun } from '@vltpkg/graph-run'\nimport type { PathScurry } from 'path-scurry'\nimport type { DepID } from '@vltpkg/dep-id'\nimport type { Diff } from '../diff.ts'\nimport type { Node } from '../node.ts'\nimport { nonEmptyList } from '../non-empty-list.ts'\nimport { optionalFail } from './optional-fail.ts'\nimport { binChmod } from './bin-chmod.ts'\n\n/**\n * Returns an object mapping registries to the names of the packages built.\n */\nexport type BuildResult = {\n success: Node[]\n failure: Node[]\n}\n\nexport const build = async (\n diff: Diff,\n packageJson: PackageJson,\n scurry: PathScurry,\n allowScriptsNodes: Set<DepID>,\n): Promise<BuildResult> => {\n const graph = diff.to\n const nodes = nonEmptyList([...graph.importers])\n const res: BuildResult = { success: [], failure: [] }\n\n // determine if scripts should run - check if node is in allowed set\n const shouldRunScripts = (node: Node): boolean =>\n allowScriptsNodes.has(node.id)\n\n /* c8 ignore next - all graphs have at least one importer */\n if (!nodes) return res\n\n await graphRun<Node, unknown>({\n graph: nodes,\n visit: async (node: Node, signal, path) => {\n // if it's not an importer or an added node, nothing to do.\n // TODO: only build importers if it has changed deps, there's never\n // been a previous build, or it contains something newer than the\n // most recent build.\n // For now, just always build all importers, because we don't\n // track all that other stuff.\n\n if (\n !node.importer &&\n (!diff.nodes.add.has(node) || !shouldRunScripts(node))\n )\n return\n\n try {\n await visit(packageJson, scurry, node, signal, path)\n if (!node.importer) {\n node.buildState = 'built'\n res.success.push(node)\n }\n /* c8 ignore start - windows on CI is missing those tests */\n } catch (err) {\n // Check if this is an optional failure that was handled\n if (node.optional) {\n node.buildState = 'failed'\n res.failure.push(node)\n // Let optionalFail handle the error\n await Promise.reject(err).catch(optionalFail(diff, node))\n } else {\n // Re-throw non-optional failures\n throw err\n }\n }\n /* c8 ignore stop */\n },\n\n getDeps: node => {\n const deps: Node[] = []\n for (const { to } of node.edgesOut.values()) {\n /* c8 ignore next - vanishingly unlikely in practice */\n if (to) deps.push(to)\n }\n return deps\n },\n })\n\n return res\n}\n\nconst visit = async (\n packageJson: PackageJson,\n scurry: PathScurry,\n node: Node,\n signal: AbortSignal,\n _path: Node[],\n): Promise<void> => {\n // at this point we might have to read the manifest from disk if it's\n // currently nullish, that could happen in a scenario where the ideal\n // graph is from a lockfile and there's no actual graph available\n // to hydrate the manifest data from.\n node.manifest ??= packageJson.read(node.resolvedLocation(scurry))\n const { manifest } = node\n const { scripts = {} } = manifest\n\n const {\n install,\n preinstall,\n postinstall,\n prepare,\n preprepare,\n postprepare,\n } = scripts\n\n // if it has install script, run it\n const runInstall = !!(install || preinstall || postinstall)\n if (runInstall) {\n await run({\n signal,\n arg0: 'install',\n ignoreMissing: true,\n packageJson,\n cwd: node.resolvedLocation(scurry),\n projectRoot: node.projectRoot,\n manifest,\n })\n }\n\n // if it's an importer or git, run prepare\n const prepable =\n node.id.startsWith('git') || node.importer || !node.inVltStore()\n const runPrepare =\n !!(prepare || preprepare || postprepare) && prepable\n\n if (runPrepare) {\n await run({\n signal,\n arg0: 'prepare',\n ignoreMissing: true,\n packageJson,\n cwd: node.resolvedLocation(scurry),\n projectRoot: node.projectRoot,\n manifest,\n })\n }\n\n await binChmod(node, scurry)\n}\n"]}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/reify/build.ts"],"names":[],"mappings":"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","sourcesContent":["// walk the graph of added nodes, building and chmoding their bins\n// at the end, we get back to the importers, and run their prepare\n// script as well as install script.\n\nimport { join } from 'node:path'\nimport type { PackageJson } from '@vltpkg/package-json'\nimport { run } from '@vltpkg/run'\nimport { graphRun } from '@vltpkg/graph-run'\nimport type { PathScurry } from 'path-scurry'\nimport type { DepID } from '@vltpkg/dep-id'\nimport type { Diff } from '../diff.ts'\nimport type { Node } from '../node.ts'\nimport { nonEmptyList } from '../non-empty-list.ts'\nimport { optionalFail } from './optional-fail.ts'\nimport { binChmod } from './bin-chmod.ts'\n\n/**\n * Returns an object mapping registries to the names of the packages built.\n */\nexport type BuildResult = {\n success: Node[]\n failure: Node[]\n}\n\nexport const build = async (\n diff: Diff,\n packageJson: PackageJson,\n scurry: PathScurry,\n allowScriptsNodes: Set<DepID>,\n): Promise<BuildResult> => {\n const graph = diff.to\n const nodes = nonEmptyList([...graph.importers])\n const res: BuildResult = { success: [], failure: [] }\n\n // determine if scripts should run - check if node is in allowed set\n const shouldRunScripts = (node: Node): boolean =>\n allowScriptsNodes.has(node.id)\n\n /* c8 ignore next - all graphs have at least one importer */\n if (!nodes) return res\n\n await graphRun<Node, unknown>({\n graph: nodes,\n visit: async (node: Node, signal, path) => {\n // if it's not an importer or an added node, nothing to do.\n // TODO: only build importers if it has changed deps, there's never\n // been a previous build, or it contains something newer than the\n // most recent build.\n // For now, just always build all importers, because we don't\n // track all that other stuff.\n\n if (\n !node.importer &&\n (!diff.nodes.add.has(node) || !shouldRunScripts(node))\n )\n return\n\n try {\n await visit(packageJson, scurry, node, signal, path)\n if (!node.importer) {\n node.buildState = 'built'\n res.success.push(node)\n }\n /* c8 ignore start - windows on CI is missing those tests */\n } catch (err) {\n // Check if this is an optional failure that was handled\n if (node.optional) {\n node.buildState = 'failed'\n res.failure.push(node)\n // Let optionalFail handle the error\n await Promise.reject(err).catch(optionalFail(diff, node))\n } else {\n // Re-throw non-optional failures\n throw err\n }\n }\n /* c8 ignore stop */\n },\n\n getDeps: node => {\n const deps: Node[] = []\n for (const { to } of node.edgesOut.values()) {\n /* c8 ignore next - vanishingly unlikely in practice */\n if (to) deps.push(to)\n }\n return deps\n },\n })\n\n return res\n}\n\nconst visit = async (\n packageJson: PackageJson,\n scurry: PathScurry,\n node: Node,\n signal: AbortSignal,\n _path: Node[],\n): Promise<void> => {\n // at this point we might have to read the manifest from disk if it's\n // currently nullish, that could happen in a scenario where the ideal\n // graph is from a lockfile and there's no actual graph available\n // to hydrate the manifest data from.\n node.manifest ??= packageJson.read(node.resolvedLocation(scurry))\n const { manifest } = node\n const { scripts = {} } = manifest\n\n const {\n install,\n preinstall,\n postinstall,\n prepare,\n preprepare,\n postprepare,\n } = scripts\n\n // Check for binding.gyp file (npm's implicit install detection)\n // \"If there is a binding.gyp file in the root of your package and you\n // haven't defined your own install or preinstall scripts, npm will default\n // the install command to compile using node-gyp via node-gyp rebuild\"\n const hasBindingGyp =\n scurry\n .lstatSync(join(node.resolvedLocation(scurry), 'binding.gyp'))\n ?.isFile() ?? false\n const hasImplicitInstall = hasBindingGyp && !install && !preinstall\n\n // if it has install script or binding.gyp (implicit install), run it\n const runInstall =\n !!(install || preinstall || postinstall) || hasImplicitInstall\n if (runInstall) {\n await run({\n signal,\n arg0: 'install',\n ignoreMissing: true,\n packageJson,\n cwd: node.resolvedLocation(scurry),\n projectRoot: node.projectRoot,\n manifest,\n })\n }\n\n // if it's an importer or git, run prepare\n const prepable =\n node.id.startsWith('git') || node.importer || !node.inVltStore()\n const runPrepare =\n !!(prepare || preprepare || postprepare) && prepable\n\n if (runPrepare) {\n await run({\n signal,\n arg0: 'prepare',\n ignoreMissing: true,\n packageJson,\n cwd: node.resolvedLocation(scurry),\n projectRoot: node.projectRoot,\n manifest,\n })\n }\n\n await binChmod(node, scurry)\n}\n"]}
@@ -1,3 +1,5 @@
1
+ import type { PathScurry } from 'path-scurry';
2
+ import type { PackageJson } from '@vltpkg/package-json';
1
3
  import type { Diff } from '../diff.ts';
2
4
  import type { Node } from '../node.ts';
3
5
  /**
@@ -14,6 +16,14 @@ export type CheckNeededBuildOptions = {
14
16
  * The diff object containing nodes to process
15
17
  */
16
18
  diff: Diff;
19
+ /**
20
+ * PathScurry instance for filesystem access
21
+ */
22
+ scurry: PathScurry;
23
+ /**
24
+ * PackageJson instance for reading manifests from disk
25
+ */
26
+ packageJson: PackageJson;
17
27
  };
18
28
  /**
19
29
  * Check which nodes need to be built and set buildState accordingly
@@ -1 +1 @@
1
- {"version":3,"file":"check-needed-build.d.ts","sourceRoot":"","sources":["../../src/reify/check-needed-build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,eAAe,EAAE,IAAI,EAAE,CAAA;CACxB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC;;OAEG;IACH,IAAI,EAAE,IAAI,CAAA;CACX,CAAA;AAuCD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,YAClB,uBAAuB,KAC/B,SAgBF,CAAA"}
1
+ {"version":3,"file":"check-needed-build.d.ts","sourceRoot":"","sources":["../../src/reify/check-needed-build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAGtC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,eAAe,EAAE,IAAI,EAAE,CAAA;CACxB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC;;OAEG;IACH,IAAI,EAAE,IAAI,CAAA;IACV;;OAEG;IACH,MAAM,EAAE,UAAU,CAAA;IAClB;;OAEG;IACH,WAAW,EAAE,WAAW,CAAA;CACzB,CAAA;AAkED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,YAClB,uBAAuB,KAC/B,SAkBF,CAAA"}
@@ -1,17 +1,30 @@
1
+ import { join } from 'node:path';
1
2
  /**
2
3
  * Checks if a node needs to be built based on the conditions from build.ts:
3
4
  * 1. Has install lifecycle scripts (install, preinstall, postinstall)
4
- * 2. Is an importer or git dependency with prepare scripts (prepare, preprepare, postprepare)
5
- * 3. Has binary files that need to be linked
5
+ * 2. Has binding.gyp file with no install/preinstall scripts (implicit install)
6
+ * 3. Is an importer or git dependency with prepare scripts (prepare, preprepare, postprepare)
7
+ * 4. Has binary files that need to be linked
6
8
  */
7
- const nodeNeedsBuild = (node) => {
9
+ const nodeNeedsBuild = (node, scurry, packageJson) => {
8
10
  // If the node has already been built during reify, no need to build again
9
11
  if (node.built)
10
12
  return false;
11
- const { manifest } = node;
12
- /* c8 ignore next */
13
- if (!manifest)
14
- return false;
13
+ // If the manifest is not available on the node, read it from disk.
14
+ // This can happen when the ideal graph is loaded from a lockfile
15
+ // and there's no actual graph available to hydrate the manifest data from.
16
+ let manifest = node.manifest;
17
+ if (!manifest) {
18
+ try {
19
+ manifest = packageJson.read(node.resolvedLocation(scurry));
20
+ node.manifest = manifest;
21
+ }
22
+ catch {
23
+ // If the manifest cannot be read (missing/corrupted), treat as
24
+ // "no build needed" to avoid failing the entire reification.
25
+ return false;
26
+ }
27
+ }
15
28
  const { scripts = {} } = manifest;
16
29
  // Check for install lifecycle scripts
17
30
  const runInstall = !!(scripts.install ||
@@ -19,6 +32,15 @@ const nodeNeedsBuild = (node) => {
19
32
  scripts.postinstall);
20
33
  if (runInstall)
21
34
  return true;
35
+ // Check for binding.gyp file (npm's implicit install detection)
36
+ // "If there is a binding.gyp file in the root of your package and you
37
+ // haven't defined your own install or preinstall scripts, npm will default
38
+ // the install command to compile using node-gyp via node-gyp rebuild"
39
+ const hasBindingGyp = scurry
40
+ .lstatSync(join(node.resolvedLocation(scurry), 'binding.gyp'))
41
+ ?.isFile() ?? false;
42
+ if (hasBindingGyp && !scripts.install && !scripts.preinstall)
43
+ return true;
22
44
  // Check for prepare scripts on importers or git dependencies
23
45
  const prepable = node.id.startsWith('git') || node.importer || !node.inVltStore();
24
46
  const runPrepare = !!((scripts.prepare || scripts.preprepare || scripts.postprepare)
@@ -35,9 +57,9 @@ const nodeNeedsBuild = (node) => {
35
57
  * @returns {BuildData} The BuildData object containing Node objects that need building
36
58
  */
37
59
  export const checkNeededBuild = (options) => {
38
- const { diff } = options;
60
+ const { diff, scurry, packageJson } = options;
39
61
  // Filter nodes to only include those that actually need to be built
40
- const nodesToBuild = [...diff.nodes.add].filter(nodeNeedsBuild);
62
+ const nodesToBuild = [...diff.nodes.add].filter(node => nodeNeedsBuild(node, scurry, packageJson));
41
63
  // Set buildState = 'needed' on all nodes that require building
42
64
  for (const node of nodesToBuild) {
43
65
  node.buildState = 'needed';
@@ -1 +1 @@
1
- {"version":3,"file":"check-needed-build.js","sourceRoot":"","sources":["../../src/reify/check-needed-build.ts"],"names":[],"mappings":"AAoBA;;;;;GAKG;AACH,MAAM,cAAc,GAAG,CAAC,IAAU,EAAW,EAAE;IAC7C,0EAA0E;IAC1E,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAE5B,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;IACzB,oBAAoB;IACpB,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAA;IAE3B,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,QAAQ,CAAA;IAEjC,sCAAsC;IACtC,MAAM,UAAU,GAAG,CAAC,CAAC,CACnB,OAAO,CAAC,OAAO;QACf,OAAO,CAAC,UAAU;QAClB,OAAO,CAAC,WAAW,CACpB,CAAA;IACD,IAAI,UAAU;QAAE,OAAO,IAAI,CAAA;IAE3B,6DAA6D;IAC7D,MAAM,QAAQ,GACZ,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAA;IAClE,MAAM,UAAU,GACd,CAAC,CAAC,CACA,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC;IAC9D,sBAAsB;KACvB,IAAI,QAAQ,CAAA;IACf,IAAI,UAAU;QAAE,OAAO,IAAI,CAAA;IAE3B,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,OAAgC,EACrB,EAAE;IACb,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;IAExB,oEAAoE;IACpE,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IAE/D,+DAA+D;IAC/D,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAA;IAC5B,CAAC;IAED,MAAM,SAAS,GAAc;QAC3B,eAAe,EAAE,YAAY;KAC9B,CAAA;IAED,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA","sourcesContent":["import type { Diff } from '../diff.ts'\nimport type { Node } from '../node.ts'\n\n/**\n * Build data containing the queue of DepIDs that need building\n */\nexport type BuildData = {\n needsBuildNodes: Node[]\n}\n\n/**\n * Options for checking needed build data\n */\nexport type CheckNeededBuildOptions = {\n /**\n * The diff object containing nodes to process\n */\n diff: Diff\n}\n\n/**\n * Checks if a node needs to be built based on the conditions from build.ts:\n * 1. Has install lifecycle scripts (install, preinstall, postinstall)\n * 2. Is an importer or git dependency with prepare scripts (prepare, preprepare, postprepare)\n * 3. Has binary files that need to be linked\n */\nconst nodeNeedsBuild = (node: Node): boolean => {\n // If the node has already been built during reify, no need to build again\n if (node.built) return false\n\n const { manifest } = node\n /* c8 ignore next */\n if (!manifest) return false\n\n const { scripts = {} } = manifest\n\n // Check for install lifecycle scripts\n const runInstall = !!(\n scripts.install ||\n scripts.preinstall ||\n scripts.postinstall\n )\n if (runInstall) return true\n\n // Check for prepare scripts on importers or git dependencies\n const prepable =\n node.id.startsWith('git') || node.importer || !node.inVltStore()\n const runPrepare =\n !!(\n (scripts.prepare || scripts.preprepare || scripts.postprepare)\n /* c8 ignore next 2 */\n ) && prepable\n if (runPrepare) return true\n\n return false\n}\n\n/**\n * Check which nodes need to be built and set buildState accordingly\n * Marks nodes with buildState = 'needed' for those that require\n * install lifecycle scripts as part of `vlt build`\n * @returns {BuildData} The BuildData object containing Node objects that need building\n */\nexport const checkNeededBuild = (\n options: CheckNeededBuildOptions,\n): BuildData => {\n const { diff } = options\n\n // Filter nodes to only include those that actually need to be built\n const nodesToBuild = [...diff.nodes.add].filter(nodeNeedsBuild)\n\n // Set buildState = 'needed' on all nodes that require building\n for (const node of nodesToBuild) {\n node.buildState = 'needed'\n }\n\n const buildData: BuildData = {\n needsBuildNodes: nodesToBuild,\n }\n\n return buildData\n}\n"]}
1
+ {"version":3,"file":"check-needed-build.js","sourceRoot":"","sources":["../../src/reify/check-needed-build.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AA2BhC;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,CACrB,IAAU,EACV,MAAkB,EAClB,WAAwB,EACf,EAAE;IACX,0EAA0E;IAC1E,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAE5B,mEAAmE;IACnE,iEAAiE;IACjE,2EAA2E;IAC3E,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;IAC5B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,CAAC;YACH,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAA;YAC1D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,+DAA+D;YAC/D,6DAA6D;YAC7D,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,QAAQ,CAAA;IAEjC,sCAAsC;IACtC,MAAM,UAAU,GAAG,CAAC,CAAC,CACnB,OAAO,CAAC,OAAO;QACf,OAAO,CAAC,UAAU;QAClB,OAAO,CAAC,WAAW,CACpB,CAAA;IACD,IAAI,UAAU;QAAE,OAAO,IAAI,CAAA;IAE3B,gEAAgE;IAChE,sEAAsE;IACtE,2EAA2E;IAC3E,sEAAsE;IACtE,MAAM,aAAa,GACjB,MAAM;SACH,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC;QAC9D,EAAE,MAAM,EAAE,IAAI,KAAK,CAAA;IACvB,IAAI,aAAa,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU;QAC1D,OAAO,IAAI,CAAA;IAEb,6DAA6D;IAC7D,MAAM,QAAQ,GACZ,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAA;IAClE,MAAM,UAAU,GACd,CAAC,CAAC,CACA,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC;IAC9D,sBAAsB;KACvB,IAAI,QAAQ,CAAA;IACf,IAAI,UAAU;QAAE,OAAO,IAAI,CAAA;IAE3B,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,OAAgC,EACrB,EAAE;IACb,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAA;IAE7C,oEAAoE;IACpE,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CACrD,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAC1C,CAAA;IAED,+DAA+D;IAC/D,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAA;IAC5B,CAAC;IAED,MAAM,SAAS,GAAc;QAC3B,eAAe,EAAE,YAAY;KAC9B,CAAA;IAED,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA","sourcesContent":["import type { PathScurry } from 'path-scurry'\nimport type { PackageJson } from '@vltpkg/package-json'\nimport type { Diff } from '../diff.ts'\nimport type { Node } from '../node.ts'\nimport { join } from 'node:path'\n\n/**\n * Build data containing the queue of DepIDs that need building\n */\nexport type BuildData = {\n needsBuildNodes: Node[]\n}\n\n/**\n * Options for checking needed build data\n */\nexport type CheckNeededBuildOptions = {\n /**\n * The diff object containing nodes to process\n */\n diff: Diff\n /**\n * PathScurry instance for filesystem access\n */\n scurry: PathScurry\n /**\n * PackageJson instance for reading manifests from disk\n */\n packageJson: PackageJson\n}\n\n/**\n * Checks if a node needs to be built based on the conditions from build.ts:\n * 1. Has install lifecycle scripts (install, preinstall, postinstall)\n * 2. Has binding.gyp file with no install/preinstall scripts (implicit install)\n * 3. Is an importer or git dependency with prepare scripts (prepare, preprepare, postprepare)\n * 4. Has binary files that need to be linked\n */\nconst nodeNeedsBuild = (\n node: Node,\n scurry: PathScurry,\n packageJson: PackageJson,\n): boolean => {\n // If the node has already been built during reify, no need to build again\n if (node.built) return false\n\n // If the manifest is not available on the node, read it from disk.\n // This can happen when the ideal graph is loaded from a lockfile\n // and there's no actual graph available to hydrate the manifest data from.\n let manifest = node.manifest\n if (!manifest) {\n try {\n manifest = packageJson.read(node.resolvedLocation(scurry))\n node.manifest = manifest\n } catch {\n // If the manifest cannot be read (missing/corrupted), treat as\n // \"no build needed\" to avoid failing the entire reification.\n return false\n }\n }\n\n const { scripts = {} } = manifest\n\n // Check for install lifecycle scripts\n const runInstall = !!(\n scripts.install ||\n scripts.preinstall ||\n scripts.postinstall\n )\n if (runInstall) return true\n\n // Check for binding.gyp file (npm's implicit install detection)\n // \"If there is a binding.gyp file in the root of your package and you\n // haven't defined your own install or preinstall scripts, npm will default\n // the install command to compile using node-gyp via node-gyp rebuild\"\n const hasBindingGyp =\n scurry\n .lstatSync(join(node.resolvedLocation(scurry), 'binding.gyp'))\n ?.isFile() ?? false\n if (hasBindingGyp && !scripts.install && !scripts.preinstall)\n return true\n\n // Check for prepare scripts on importers or git dependencies\n const prepable =\n node.id.startsWith('git') || node.importer || !node.inVltStore()\n const runPrepare =\n !!(\n (scripts.prepare || scripts.preprepare || scripts.postprepare)\n /* c8 ignore next 2 */\n ) && prepable\n if (runPrepare) return true\n\n return false\n}\n\n/**\n * Check which nodes need to be built and set buildState accordingly\n * Marks nodes with buildState = 'needed' for those that require\n * install lifecycle scripts as part of `vlt build`\n * @returns {BuildData} The BuildData object containing Node objects that need building\n */\nexport const checkNeededBuild = (\n options: CheckNeededBuildOptions,\n): BuildData => {\n const { diff, scurry, packageJson } = options\n\n // Filter nodes to only include those that actually need to be built\n const nodesToBuild = [...diff.nodes.add].filter(node =>\n nodeNeedsBuild(node, scurry, packageJson),\n )\n\n // Set buildState = 'needed' on all nodes that require building\n for (const node of nodesToBuild) {\n node.buildState = 'needed'\n }\n\n const buildData: BuildData = {\n needsBuildNodes: nodesToBuild,\n }\n\n return buildData\n}\n"]}
@@ -119,7 +119,7 @@ const reify_ = async (options, diff, remover) => {
119
119
  await internalHoist(diff.to, options, remover);
120
120
  // looks up all nodes setting buildState = 'needed'
121
121
  // on nodes that require building
122
- checkNeededBuild({ diff });
122
+ checkNeededBuild({ diff, scurry, packageJson });
123
123
  // Filter nodes allowed to run scripts if allowScripts query is provided
124
124
  const allowScriptsNodes = await filterNodesByQuery(diff.to, allowScripts);
125
125
  // ensure that all added bins are chmod +x
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reify/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { graphStep } from '@vltpkg/output'\nimport type { PackageInfoClient } from '@vltpkg/package-info'\nimport type { RollbackRemove } from '@vltpkg/rollback-remove'\nimport { availableParallelism } from 'node:os'\nimport { callLimit } from 'promise-call-limit'\nimport type { DepID } from '@vltpkg/dep-id'\nimport type { LoadOptions } from '../actual/load.ts'\nimport { load as loadActual } from '../actual/load.ts'\nimport type {\n AddImportersDependenciesMap,\n RemoveImportersDependenciesMap,\n} from '../dependencies.ts'\nimport { Diff } from '../diff.ts'\nimport type { Graph } from '../graph.ts'\nimport type { GraphModifier } from '../modifiers.ts'\nimport {\n lockfileData,\n saveData,\n saveHidden,\n} from '../lockfile/save.ts'\nimport { addEdges } from './add-edges.ts'\nimport { addNodes } from './add-nodes.ts'\nimport { build } from './build.ts'\nimport { deleteEdges } from './delete-edges.ts'\nimport { checkNeededBuild } from './check-needed-build.ts'\nimport { deleteNodes } from './delete-nodes.ts'\nimport { internalHoist } from './internal-hoist.ts'\nimport { rollback } from './rollback.ts'\nimport { updatePackageJson } from './update-importers-package-json.ts'\nimport { copyFileSync } from 'node:fs'\nimport { Query } from '@vltpkg/query'\nimport { SecurityArchive } from '@vltpkg/security-archive'\nimport type { NodeLike } from '@vltpkg/types'\nimport { binChmodAll } from './bin-chmod.ts'\n\nconst limit = Math.max(availableParallelism() - 1, 1) * 8\n\n/**\n * Filter nodes using a DSS query string\n */\nconst filterNodesByQuery = async (\n graph: Graph,\n allowScriptsQuery?: string,\n): Promise<Set<DepID>> => {\n // shortcut no packages included\n if (\n allowScriptsQuery === ':not(*)' /* c8 ignore next */ ||\n !allowScriptsQuery\n ) {\n return new Set()\n }\n // shortcut all packages included\n if (allowScriptsQuery === '*') {\n return new Set(graph.nodes.keys())\n }\n /* c8 ignore start */\n const securityArchive =\n Query.hasSecuritySelectors(allowScriptsQuery) ?\n await SecurityArchive.start({\n nodes: [...graph.nodes.values()],\n })\n : undefined\n /* c8 ignore stop */\n\n const edges = graph.edges\n const nodes = new Set<NodeLike>(graph.nodes.values())\n const importers = graph.importers\n\n const query = new Query({\n edges,\n nodes,\n importers,\n securityArchive,\n })\n\n const { nodes: resultNodes } = await query.search(\n allowScriptsQuery,\n {\n signal: new AbortController().signal,\n },\n )\n\n return new Set(resultNodes.map(node => node.id))\n}\n\n// - [ ] depid's with peer resolutions\n// - [ ] depid shortening\n\nexport type ReifyOptions = LoadOptions & {\n add?: AddImportersDependenciesMap\n allowScripts: string\n remove?: RemoveImportersDependenciesMap\n graph: Graph\n actual?: Graph\n packageInfo: PackageInfoClient\n modifiers?: GraphModifier\n remover: RollbackRemove\n}\n\nexport type ReifyResult = {\n /**\n * The diff object that was used to reify the project.\n */\n diff: Diff\n /**\n * Optional queue of DepIDs that requires building (running lifecycle scripts\n * and binary linking) after the reification is complete.\n */\n buildQueue?: DepID[]\n}\n\n/**\n * Make the current project match the supplied graph.\n */\nexport const reify = async (\n options: ReifyOptions,\n): Promise<ReifyResult> => {\n const done = graphStep('reify')\n\n const { graph, scurry, remover } = options\n\n const actual =\n options.actual ??\n loadActual({\n ...options,\n loadManifests: true,\n })\n\n const diff = new Diff(actual, graph)\n const noModifiedDependencies =\n !options.add?.modifiedDependencies &&\n !options.remove?.modifiedDependencies\n const skipOptionalOnly = noModifiedDependencies && diff.optionalOnly\n const res: ReifyResult = { diff }\n if (!diff.hasChanges() || skipOptionalOnly) {\n // nothing to do, so just return the diff\n done()\n return res\n }\n\n let success = false\n try {\n const { buildQueue } = await reify_(options, diff, remover)\n remover.confirm()\n success = true\n res.buildQueue = buildQueue\n } finally {\n /* c8 ignore start */\n if (!success) {\n await rollback(remover, diff, scurry).catch(() => {})\n }\n /* c8 ignore stop */\n }\n\n done()\n\n return res\n}\n\nconst reify_ = async (\n options: ReifyOptions,\n diff: Diff,\n remover: RollbackRemove,\n): Promise<Omit<ReifyResult, 'diff'>> => {\n const res: Omit<ReifyResult, 'diff'> = {}\n const {\n add,\n remove,\n packageInfo,\n packageJson,\n scurry,\n allowScripts,\n } = options\n const saveImportersPackageJson =\n /* c8 ignore next */\n add?.modifiedDependencies || remove?.modifiedDependencies ?\n updatePackageJson({\n add,\n remove,\n graph: options.graph,\n packageJson,\n })\n : undefined\n\n // before anything else happens, grab the ideal tree as it was resolved\n // so that we can store it in the lockfile. We do this here so that\n // any failed/removed optional deps are not reflected in the lockfile\n // data as it is saved.\n const lfData = lockfileData(options)\n const actions: (() => Promise<unknown>)[] = addNodes(\n diff,\n scurry,\n remover,\n options,\n packageInfo,\n ).concat(deleteEdges(diff, scurry, remover))\n\n // need to wait, so that the nodes exist to link to\n if (actions.length) await callLimit(actions, { limit })\n\n // create all node_modules symlinks, and link bins to nm/.bin\n const edgeActions = addEdges(diff, scurry, remover)\n if (edgeActions.length) await callLimit(edgeActions, { limit })\n\n await internalHoist(diff.to, options, remover)\n\n // looks up all nodes setting buildState = 'needed'\n // on nodes that require building\n checkNeededBuild({ diff })\n\n // Filter nodes allowed to run scripts if allowScripts query is provided\n const allowScriptsNodes = await filterNodesByQuery(\n diff.to,\n allowScripts,\n )\n\n // ensure that all added bins are chmod +x\n await binChmodAll(diff.nodes.add, scurry)\n\n // run install lifecycle scripts and link any binary files\n await build(diff, packageJson, scurry, allowScriptsNodes)\n\n // set the buildQueue on the result object containing\n // an array with all the ids of nodes that need building\n res.buildQueue = [...diff.nodes.add]\n .filter(node => node.buildState === 'needed')\n .map(node => node.id)\n\n // if we had to change the actual graph along the way,\n // make sure we do not leave behind any unreachable nodes\n // TODO: add tests to cover this\n /* c8 ignore start */\n if (diff.hadOptionalFailures) {\n for (const node of options.graph.gc().values()) {\n diff.nodes.add.delete(node)\n diff.nodes.delete.add(node)\n }\n }\n /* c8 ignore stop */\n saveHidden(options)\n\n // delete garbage from the store.\n const rmActions: Promise<unknown>[] = deleteNodes(\n diff,\n remover,\n scurry,\n )\n if (rmActions.length) await Promise.all(rmActions)\n\n // updates package.json files if anything was added / removed\n saveImportersPackageJson?.()\n\n // write the ideal graph data to the lockfile\n saveData(lfData, scurry.resolve('vlt-lock.json'), false)\n\n // update the store config reference if a config file was used\n if (scurry.lstatSync('vlt.json')) {\n copyFileSync(\n scurry.resolve('vlt.json'),\n scurry.resolve('node_modules/.vlt/vlt.json'),\n )\n }\n\n // returns the result object\n return res\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reify/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { graphStep } from '@vltpkg/output'\nimport type { PackageInfoClient } from '@vltpkg/package-info'\nimport type { RollbackRemove } from '@vltpkg/rollback-remove'\nimport { availableParallelism } from 'node:os'\nimport { callLimit } from 'promise-call-limit'\nimport type { DepID } from '@vltpkg/dep-id'\nimport type { LoadOptions } from '../actual/load.ts'\nimport { load as loadActual } from '../actual/load.ts'\nimport type {\n AddImportersDependenciesMap,\n RemoveImportersDependenciesMap,\n} from '../dependencies.ts'\nimport { Diff } from '../diff.ts'\nimport type { Graph } from '../graph.ts'\nimport type { GraphModifier } from '../modifiers.ts'\nimport {\n lockfileData,\n saveData,\n saveHidden,\n} from '../lockfile/save.ts'\nimport { addEdges } from './add-edges.ts'\nimport { addNodes } from './add-nodes.ts'\nimport { build } from './build.ts'\nimport { deleteEdges } from './delete-edges.ts'\nimport { checkNeededBuild } from './check-needed-build.ts'\nimport { deleteNodes } from './delete-nodes.ts'\nimport { internalHoist } from './internal-hoist.ts'\nimport { rollback } from './rollback.ts'\nimport { updatePackageJson } from './update-importers-package-json.ts'\nimport { copyFileSync } from 'node:fs'\nimport { Query } from '@vltpkg/query'\nimport { SecurityArchive } from '@vltpkg/security-archive'\nimport type { NodeLike } from '@vltpkg/types'\nimport { binChmodAll } from './bin-chmod.ts'\n\nconst limit = Math.max(availableParallelism() - 1, 1) * 8\n\n/**\n * Filter nodes using a DSS query string\n */\nconst filterNodesByQuery = async (\n graph: Graph,\n allowScriptsQuery?: string,\n): Promise<Set<DepID>> => {\n // shortcut no packages included\n if (\n allowScriptsQuery === ':not(*)' /* c8 ignore next */ ||\n !allowScriptsQuery\n ) {\n return new Set()\n }\n // shortcut all packages included\n if (allowScriptsQuery === '*') {\n return new Set(graph.nodes.keys())\n }\n /* c8 ignore start */\n const securityArchive =\n Query.hasSecuritySelectors(allowScriptsQuery) ?\n await SecurityArchive.start({\n nodes: [...graph.nodes.values()],\n })\n : undefined\n /* c8 ignore stop */\n\n const edges = graph.edges\n const nodes = new Set<NodeLike>(graph.nodes.values())\n const importers = graph.importers\n\n const query = new Query({\n edges,\n nodes,\n importers,\n securityArchive,\n })\n\n const { nodes: resultNodes } = await query.search(\n allowScriptsQuery,\n {\n signal: new AbortController().signal,\n },\n )\n\n return new Set(resultNodes.map(node => node.id))\n}\n\n// - [ ] depid's with peer resolutions\n// - [ ] depid shortening\n\nexport type ReifyOptions = LoadOptions & {\n add?: AddImportersDependenciesMap\n allowScripts: string\n remove?: RemoveImportersDependenciesMap\n graph: Graph\n actual?: Graph\n packageInfo: PackageInfoClient\n modifiers?: GraphModifier\n remover: RollbackRemove\n}\n\nexport type ReifyResult = {\n /**\n * The diff object that was used to reify the project.\n */\n diff: Diff\n /**\n * Optional queue of DepIDs that requires building (running lifecycle scripts\n * and binary linking) after the reification is complete.\n */\n buildQueue?: DepID[]\n}\n\n/**\n * Make the current project match the supplied graph.\n */\nexport const reify = async (\n options: ReifyOptions,\n): Promise<ReifyResult> => {\n const done = graphStep('reify')\n\n const { graph, scurry, remover } = options\n\n const actual =\n options.actual ??\n loadActual({\n ...options,\n loadManifests: true,\n })\n\n const diff = new Diff(actual, graph)\n const noModifiedDependencies =\n !options.add?.modifiedDependencies &&\n !options.remove?.modifiedDependencies\n const skipOptionalOnly = noModifiedDependencies && diff.optionalOnly\n const res: ReifyResult = { diff }\n if (!diff.hasChanges() || skipOptionalOnly) {\n // nothing to do, so just return the diff\n done()\n return res\n }\n\n let success = false\n try {\n const { buildQueue } = await reify_(options, diff, remover)\n remover.confirm()\n success = true\n res.buildQueue = buildQueue\n } finally {\n /* c8 ignore start */\n if (!success) {\n await rollback(remover, diff, scurry).catch(() => {})\n }\n /* c8 ignore stop */\n }\n\n done()\n\n return res\n}\n\nconst reify_ = async (\n options: ReifyOptions,\n diff: Diff,\n remover: RollbackRemove,\n): Promise<Omit<ReifyResult, 'diff'>> => {\n const res: Omit<ReifyResult, 'diff'> = {}\n const {\n add,\n remove,\n packageInfo,\n packageJson,\n scurry,\n allowScripts,\n } = options\n const saveImportersPackageJson =\n /* c8 ignore next */\n add?.modifiedDependencies || remove?.modifiedDependencies ?\n updatePackageJson({\n add,\n remove,\n graph: options.graph,\n packageJson,\n })\n : undefined\n\n // before anything else happens, grab the ideal tree as it was resolved\n // so that we can store it in the lockfile. We do this here so that\n // any failed/removed optional deps are not reflected in the lockfile\n // data as it is saved.\n const lfData = lockfileData(options)\n const actions: (() => Promise<unknown>)[] = addNodes(\n diff,\n scurry,\n remover,\n options,\n packageInfo,\n ).concat(deleteEdges(diff, scurry, remover))\n\n // need to wait, so that the nodes exist to link to\n if (actions.length) await callLimit(actions, { limit })\n\n // create all node_modules symlinks, and link bins to nm/.bin\n const edgeActions = addEdges(diff, scurry, remover)\n if (edgeActions.length) await callLimit(edgeActions, { limit })\n\n await internalHoist(diff.to, options, remover)\n\n // looks up all nodes setting buildState = 'needed'\n // on nodes that require building\n checkNeededBuild({ diff, scurry, packageJson })\n\n // Filter nodes allowed to run scripts if allowScripts query is provided\n const allowScriptsNodes = await filterNodesByQuery(\n diff.to,\n allowScripts,\n )\n\n // ensure that all added bins are chmod +x\n await binChmodAll(diff.nodes.add, scurry)\n\n // run install lifecycle scripts and link any binary files\n await build(diff, packageJson, scurry, allowScriptsNodes)\n\n // set the buildQueue on the result object containing\n // an array with all the ids of nodes that need building\n res.buildQueue = [...diff.nodes.add]\n .filter(node => node.buildState === 'needed')\n .map(node => node.id)\n\n // if we had to change the actual graph along the way,\n // make sure we do not leave behind any unreachable nodes\n // TODO: add tests to cover this\n /* c8 ignore start */\n if (diff.hadOptionalFailures) {\n for (const node of options.graph.gc().values()) {\n diff.nodes.add.delete(node)\n diff.nodes.delete.add(node)\n }\n }\n /* c8 ignore stop */\n saveHidden(options)\n\n // delete garbage from the store.\n const rmActions: Promise<unknown>[] = deleteNodes(\n diff,\n remover,\n scurry,\n )\n if (rmActions.length) await Promise.all(rmActions)\n\n // updates package.json files if anything was added / removed\n saveImportersPackageJson?.()\n\n // write the ideal graph data to the lockfile\n saveData(lfData, scurry.resolve('vlt-lock.json'), false)\n\n // update the store config reference if a config file was used\n if (scurry.lstatSync('vlt.json')) {\n copyFileSync(\n scurry.resolve('vlt.json'),\n scurry.resolve('node_modules/.vlt/vlt.json'),\n )\n }\n\n // returns the result object\n return res\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vltpkg/graph",
3
3
  "description": "A library that helps understanding & expressing what happens on an install",
4
- "version": "1.0.0-rc.11",
4
+ "version": "1.0.0-rc.13",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/vltpkg/vltpkg.git",
@@ -11,26 +11,26 @@
11
11
  "dependencies": {
12
12
  "path-scurry": "^2.0.1",
13
13
  "promise-call-limit": "^3.0.2",
14
- "@vltpkg/cmd-shim": "1.0.0-rc.11",
15
- "@vltpkg/dep-id": "1.0.0-rc.11",
16
- "@vltpkg/error-cause": "1.0.0-rc.11",
17
- "@vltpkg/dss-breadcrumb": "1.0.0-rc.11",
18
- "@vltpkg/fast-split": "1.0.0-rc.11",
19
- "@vltpkg/graph-run": "1.0.0-rc.11",
20
- "@vltpkg/init": "1.0.0-rc.11",
21
- "@vltpkg/output": "1.0.0-rc.11",
22
- "@vltpkg/package-info": "1.0.0-rc.11",
23
- "@vltpkg/package-json": "1.0.0-rc.11",
24
- "@vltpkg/pick-manifest": "1.0.0-rc.11",
25
- "@vltpkg/query": "1.0.0-rc.11",
26
- "@vltpkg/rollback-remove": "1.0.0-rc.11",
27
- "@vltpkg/satisfies": "1.0.0-rc.11",
28
- "@vltpkg/run": "1.0.0-rc.11",
29
- "@vltpkg/security-archive": "1.0.0-rc.11",
30
- "@vltpkg/spec": "1.0.0-rc.11",
31
- "@vltpkg/types": "1.0.0-rc.11",
32
- "@vltpkg/vlt-json": "1.0.0-rc.11",
33
- "@vltpkg/workspaces": "1.0.0-rc.11"
14
+ "@vltpkg/cmd-shim": "1.0.0-rc.13",
15
+ "@vltpkg/dep-id": "1.0.0-rc.13",
16
+ "@vltpkg/error-cause": "1.0.0-rc.13",
17
+ "@vltpkg/fast-split": "1.0.0-rc.13",
18
+ "@vltpkg/dss-breadcrumb": "1.0.0-rc.13",
19
+ "@vltpkg/graph-run": "1.0.0-rc.13",
20
+ "@vltpkg/output": "1.0.0-rc.13",
21
+ "@vltpkg/init": "1.0.0-rc.13",
22
+ "@vltpkg/package-info": "1.0.0-rc.13",
23
+ "@vltpkg/package-json": "1.0.0-rc.13",
24
+ "@vltpkg/pick-manifest": "1.0.0-rc.13",
25
+ "@vltpkg/rollback-remove": "1.0.0-rc.13",
26
+ "@vltpkg/query": "1.0.0-rc.13",
27
+ "@vltpkg/run": "1.0.0-rc.13",
28
+ "@vltpkg/satisfies": "1.0.0-rc.13",
29
+ "@vltpkg/security-archive": "1.0.0-rc.13",
30
+ "@vltpkg/spec": "1.0.0-rc.13",
31
+ "@vltpkg/types": "1.0.0-rc.13",
32
+ "@vltpkg/vlt-json": "1.0.0-rc.13",
33
+ "@vltpkg/workspaces": "1.0.0-rc.13"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@eslint/js": "^9.39.1",
@@ -42,7 +42,7 @@
42
42
  "typedoc": "~0.27.9",
43
43
  "typescript": "5.7.3",
44
44
  "typescript-eslint": "^8.49.0",
45
- "@vltpkg/vlt-json": "1.0.0-rc.11"
45
+ "@vltpkg/vlt-json": "1.0.0-rc.13"
46
46
  },
47
47
  "license": "BSD-2-Clause-Patent",
48
48
  "engines": {