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

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.
Files changed (329) hide show
  1. package/dist/actual/load.d.ts.map +1 -0
  2. package/dist/{esm/actual → actual}/load.js +35 -14
  3. package/dist/actual/load.js.map +1 -0
  4. package/dist/{esm/browser.d.ts → browser.d.ts} +1 -1
  5. package/dist/browser.d.ts.map +1 -0
  6. package/dist/browser.js.map +1 -0
  7. package/dist/build.d.ts.map +1 -0
  8. package/dist/build.js.map +1 -0
  9. package/dist/dependencies.d.ts.map +1 -0
  10. package/dist/dependencies.js.map +1 -0
  11. package/dist/{esm/diff.d.ts → diff.d.ts} +2 -0
  12. package/dist/diff.d.ts.map +1 -0
  13. package/dist/diff.js.map +1 -0
  14. package/dist/{esm/edge.d.ts → edge.d.ts} +1 -0
  15. package/dist/edge.d.ts.map +1 -0
  16. package/dist/{esm/edge.js → edge.js} +4 -0
  17. package/dist/edge.js.map +1 -0
  18. package/dist/fixup-added-names.d.ts +16 -0
  19. package/dist/fixup-added-names.d.ts.map +1 -0
  20. package/dist/fixup-added-names.js +31 -0
  21. package/dist/fixup-added-names.js.map +1 -0
  22. package/dist/{esm/graph.d.ts → graph.d.ts} +18 -4
  23. package/dist/graph.d.ts.map +1 -0
  24. package/dist/{esm/graph.js → graph.js} +63 -40
  25. package/dist/graph.js.map +1 -0
  26. package/dist/{esm/ideal → ideal}/append-nodes.d.ts +2 -1
  27. package/dist/ideal/append-nodes.d.ts.map +1 -0
  28. package/dist/ideal/append-nodes.js +395 -0
  29. package/dist/ideal/append-nodes.js.map +1 -0
  30. package/dist/{esm/ideal → ideal}/build-ideal-from-starting-graph.d.ts +4 -4
  31. package/dist/ideal/build-ideal-from-starting-graph.d.ts.map +1 -0
  32. package/dist/ideal/build-ideal-from-starting-graph.js +70 -0
  33. package/dist/ideal/build-ideal-from-starting-graph.js.map +1 -0
  34. package/dist/ideal/build.d.ts.map +1 -0
  35. package/dist/{esm/ideal → ideal}/build.js +29 -2
  36. package/dist/ideal/build.js.map +1 -0
  37. package/dist/{esm/ideal → ideal}/get-importer-specs.d.ts +9 -2
  38. package/dist/ideal/get-importer-specs.d.ts.map +1 -0
  39. package/dist/{esm/ideal → ideal}/get-importer-specs.js +80 -5
  40. package/dist/ideal/get-importer-specs.js.map +1 -0
  41. package/dist/ideal/get-ordered-dependencies.d.ts +10 -0
  42. package/dist/ideal/get-ordered-dependencies.d.ts.map +1 -0
  43. package/dist/ideal/get-ordered-dependencies.js +42 -0
  44. package/dist/ideal/get-ordered-dependencies.js.map +1 -0
  45. package/dist/ideal/peers.d.ts +76 -0
  46. package/dist/ideal/peers.d.ts.map +1 -0
  47. package/dist/ideal/peers.js +340 -0
  48. package/dist/ideal/peers.js.map +1 -0
  49. package/dist/ideal/refresh-ideal-graph.d.ts +48 -0
  50. package/dist/ideal/refresh-ideal-graph.d.ts.map +1 -0
  51. package/dist/ideal/refresh-ideal-graph.js +79 -0
  52. package/dist/ideal/refresh-ideal-graph.js.map +1 -0
  53. package/dist/ideal/remove-satisfied-specs.d.ts.map +1 -0
  54. package/dist/ideal/remove-satisfied-specs.js.map +1 -0
  55. package/dist/ideal/types.d.ts +112 -0
  56. package/dist/ideal/types.d.ts.map +1 -0
  57. package/dist/ideal/types.js.map +1 -0
  58. package/dist/{esm/index.d.ts → index.d.ts} +2 -1
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/{esm/index.js → index.js} +1 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/{esm/install.d.ts → install.d.ts} +3 -2
  63. package/dist/install.d.ts.map +1 -0
  64. package/dist/{esm/install.js → install.js} +30 -6
  65. package/dist/install.js.map +1 -0
  66. package/dist/lockfile/load-edges.d.ts.map +1 -0
  67. package/dist/{esm/lockfile → lockfile}/load-edges.js +4 -3
  68. package/dist/lockfile/load-edges.js.map +1 -0
  69. package/dist/{esm/lockfile → lockfile}/load-nodes.d.ts +1 -1
  70. package/dist/lockfile/load-nodes.d.ts.map +1 -0
  71. package/dist/{esm/lockfile → lockfile}/load-nodes.js +16 -4
  72. package/dist/lockfile/load-nodes.js.map +1 -0
  73. package/dist/{esm/lockfile → lockfile}/load.d.ts +2 -2
  74. package/dist/lockfile/load.d.ts.map +1 -0
  75. package/dist/{esm/lockfile → lockfile}/load.js +6 -29
  76. package/dist/lockfile/load.js.map +1 -0
  77. package/dist/{esm/lockfile → lockfile}/save.d.ts +5 -1
  78. package/dist/lockfile/save.d.ts.map +1 -0
  79. package/dist/{esm/lockfile → lockfile}/save.js +23 -9
  80. package/dist/lockfile/save.js.map +1 -0
  81. package/dist/lockfile/types.d.ts.map +1 -0
  82. package/dist/lockfile/types.js.map +1 -0
  83. package/dist/modifiers.d.ts.map +1 -0
  84. package/dist/modifiers.js.map +1 -0
  85. package/dist/{esm/node.d.ts → node.d.ts} +14 -0
  86. package/dist/node.d.ts.map +1 -0
  87. package/dist/{esm/node.js → node.js} +21 -0
  88. package/dist/node.js.map +1 -0
  89. package/dist/non-empty-list.d.ts.map +1 -0
  90. package/dist/non-empty-list.js.map +1 -0
  91. package/dist/reify/add-edge.d.ts.map +1 -0
  92. package/dist/reify/add-edge.js.map +1 -0
  93. package/dist/{esm/reify → reify}/add-edges.d.ts +1 -1
  94. package/dist/reify/add-edges.d.ts.map +1 -0
  95. package/dist/{esm/reify → reify}/add-edges.js +2 -1
  96. package/dist/reify/add-edges.js.map +1 -0
  97. package/dist/reify/add-nodes.d.ts.map +1 -0
  98. package/dist/reify/add-nodes.js.map +1 -0
  99. package/dist/reify/bin-chmod.d.ts.map +1 -0
  100. package/dist/reify/bin-chmod.js.map +1 -0
  101. package/dist/reify/build.d.ts.map +1 -0
  102. package/dist/{esm/reify → reify}/build.js +1 -1
  103. package/dist/reify/build.js.map +1 -0
  104. package/dist/reify/calculate-save-value.d.ts.map +1 -0
  105. package/dist/reify/calculate-save-value.js.map +1 -0
  106. package/dist/reify/check-needed-build.d.ts.map +1 -0
  107. package/dist/reify/check-needed-build.js.map +1 -0
  108. package/dist/reify/delete-edge.d.ts.map +1 -0
  109. package/dist/reify/delete-edge.js.map +1 -0
  110. package/dist/reify/delete-edges.d.ts.map +1 -0
  111. package/dist/reify/delete-edges.js.map +1 -0
  112. package/dist/reify/delete-nodes.d.ts.map +1 -0
  113. package/dist/reify/delete-nodes.js.map +1 -0
  114. package/dist/reify/extract-node.d.ts.map +1 -0
  115. package/dist/{esm/reify → reify}/extract-node.js +10 -2
  116. package/dist/reify/extract-node.js.map +1 -0
  117. package/dist/reify/index.d.ts.map +1 -0
  118. package/dist/{esm/reify → reify}/index.js +1 -1
  119. package/dist/reify/index.js.map +1 -0
  120. package/dist/reify/internal-hoist.d.ts.map +1 -0
  121. package/dist/reify/internal-hoist.js.map +1 -0
  122. package/dist/reify/optional-fail.d.ts.map +1 -0
  123. package/dist/reify/optional-fail.js.map +1 -0
  124. package/dist/reify/rollback.d.ts.map +1 -0
  125. package/dist/reify/rollback.js.map +1 -0
  126. package/dist/{esm/reify → reify}/update-importers-package-json.d.ts +1 -1
  127. package/dist/reify/update-importers-package-json.d.ts.map +1 -0
  128. package/dist/{esm/reify → reify}/update-importers-package-json.js +19 -16
  129. package/dist/reify/update-importers-package-json.js.map +1 -0
  130. package/dist/remove-optional-subgraph.d.ts.map +1 -0
  131. package/dist/remove-optional-subgraph.js.map +1 -0
  132. package/dist/resolve-save-type.d.ts.map +1 -0
  133. package/dist/resolve-save-type.js.map +1 -0
  134. package/dist/stringify-node.d.ts.map +1 -0
  135. package/dist/{esm/stringify-node.js → stringify-node.js} +10 -1
  136. package/dist/stringify-node.js.map +1 -0
  137. package/dist/transfer-data/load.d.ts.map +1 -0
  138. package/dist/transfer-data/load.js.map +1 -0
  139. package/dist/uninstall.d.ts.map +1 -0
  140. package/dist/{esm/uninstall.js → uninstall.js} +10 -0
  141. package/dist/uninstall.js.map +1 -0
  142. package/dist/update.d.ts.map +1 -0
  143. package/dist/{esm/update.js → update.js} +10 -0
  144. package/dist/update.js.map +1 -0
  145. package/dist/virtual-root.d.ts.map +1 -0
  146. package/dist/virtual-root.js.map +1 -0
  147. package/dist/visualization/human-readable-output.d.ts.map +1 -0
  148. package/dist/{esm/visualization → visualization}/human-readable-output.js +7 -2
  149. package/dist/visualization/human-readable-output.js.map +1 -0
  150. package/dist/{esm/visualization → visualization}/json-output.d.ts +2 -1
  151. package/dist/visualization/json-output.d.ts.map +1 -0
  152. package/dist/{esm/visualization → visualization}/json-output.js +2 -2
  153. package/dist/visualization/json-output.js.map +1 -0
  154. package/dist/visualization/mermaid-output.d.ts.map +1 -0
  155. package/dist/{esm/visualization → visualization}/mermaid-output.js +57 -16
  156. package/dist/visualization/mermaid-output.js.map +1 -0
  157. package/dist/visualization/object-like-output.d.ts.map +1 -0
  158. package/dist/visualization/object-like-output.js.map +1 -0
  159. package/package.json +34 -50
  160. package/dist/esm/actual/load.d.ts.map +0 -1
  161. package/dist/esm/actual/load.js.map +0 -1
  162. package/dist/esm/browser.d.ts.map +0 -1
  163. package/dist/esm/browser.js.map +0 -1
  164. package/dist/esm/build.d.ts.map +0 -1
  165. package/dist/esm/build.js.map +0 -1
  166. package/dist/esm/dependencies.d.ts.map +0 -1
  167. package/dist/esm/dependencies.js.map +0 -1
  168. package/dist/esm/diff.d.ts.map +0 -1
  169. package/dist/esm/diff.js.map +0 -1
  170. package/dist/esm/edge.d.ts.map +0 -1
  171. package/dist/esm/edge.js.map +0 -1
  172. package/dist/esm/graph.d.ts.map +0 -1
  173. package/dist/esm/graph.js.map +0 -1
  174. package/dist/esm/ideal/add-nodes.d.ts +0 -34
  175. package/dist/esm/ideal/add-nodes.d.ts.map +0 -1
  176. package/dist/esm/ideal/add-nodes.js +0 -39
  177. package/dist/esm/ideal/add-nodes.js.map +0 -1
  178. package/dist/esm/ideal/append-nodes.d.ts.map +0 -1
  179. package/dist/esm/ideal/append-nodes.js +0 -288
  180. package/dist/esm/ideal/append-nodes.js.map +0 -1
  181. package/dist/esm/ideal/build-ideal-from-starting-graph.d.ts.map +0 -1
  182. package/dist/esm/ideal/build-ideal-from-starting-graph.js +0 -55
  183. package/dist/esm/ideal/build-ideal-from-starting-graph.js.map +0 -1
  184. package/dist/esm/ideal/build.d.ts.map +0 -1
  185. package/dist/esm/ideal/build.js.map +0 -1
  186. package/dist/esm/ideal/get-importer-specs.d.ts.map +0 -1
  187. package/dist/esm/ideal/get-importer-specs.js.map +0 -1
  188. package/dist/esm/ideal/remove-nodes.d.ts +0 -7
  189. package/dist/esm/ideal/remove-nodes.d.ts.map +0 -1
  190. package/dist/esm/ideal/remove-nodes.js +0 -19
  191. package/dist/esm/ideal/remove-nodes.js.map +0 -1
  192. package/dist/esm/ideal/remove-satisfied-specs.d.ts.map +0 -1
  193. package/dist/esm/ideal/remove-satisfied-specs.js.map +0 -1
  194. package/dist/esm/ideal/types.d.ts +0 -35
  195. package/dist/esm/ideal/types.d.ts.map +0 -1
  196. package/dist/esm/ideal/types.js.map +0 -1
  197. package/dist/esm/index.d.ts.map +0 -1
  198. package/dist/esm/index.js.map +0 -1
  199. package/dist/esm/install.d.ts.map +0 -1
  200. package/dist/esm/install.js.map +0 -1
  201. package/dist/esm/lockfile/load-edges.d.ts.map +0 -1
  202. package/dist/esm/lockfile/load-edges.js.map +0 -1
  203. package/dist/esm/lockfile/load-nodes.d.ts.map +0 -1
  204. package/dist/esm/lockfile/load-nodes.js.map +0 -1
  205. package/dist/esm/lockfile/load.d.ts.map +0 -1
  206. package/dist/esm/lockfile/load.js.map +0 -1
  207. package/dist/esm/lockfile/save.d.ts.map +0 -1
  208. package/dist/esm/lockfile/save.js.map +0 -1
  209. package/dist/esm/lockfile/types.d.ts.map +0 -1
  210. package/dist/esm/lockfile/types.js.map +0 -1
  211. package/dist/esm/modifiers.d.ts.map +0 -1
  212. package/dist/esm/modifiers.js.map +0 -1
  213. package/dist/esm/node.d.ts.map +0 -1
  214. package/dist/esm/node.js.map +0 -1
  215. package/dist/esm/non-empty-list.d.ts.map +0 -1
  216. package/dist/esm/non-empty-list.js.map +0 -1
  217. package/dist/esm/package.json +0 -3
  218. package/dist/esm/reify/add-edge.d.ts.map +0 -1
  219. package/dist/esm/reify/add-edge.js.map +0 -1
  220. package/dist/esm/reify/add-edges.d.ts.map +0 -1
  221. package/dist/esm/reify/add-edges.js.map +0 -1
  222. package/dist/esm/reify/add-nodes.d.ts.map +0 -1
  223. package/dist/esm/reify/add-nodes.js.map +0 -1
  224. package/dist/esm/reify/bin-chmod.d.ts.map +0 -1
  225. package/dist/esm/reify/bin-chmod.js.map +0 -1
  226. package/dist/esm/reify/build.d.ts.map +0 -1
  227. package/dist/esm/reify/build.js.map +0 -1
  228. package/dist/esm/reify/calculate-save-value.d.ts.map +0 -1
  229. package/dist/esm/reify/calculate-save-value.js.map +0 -1
  230. package/dist/esm/reify/check-needed-build.d.ts.map +0 -1
  231. package/dist/esm/reify/check-needed-build.js.map +0 -1
  232. package/dist/esm/reify/delete-edge.d.ts.map +0 -1
  233. package/dist/esm/reify/delete-edge.js.map +0 -1
  234. package/dist/esm/reify/delete-edges.d.ts.map +0 -1
  235. package/dist/esm/reify/delete-edges.js.map +0 -1
  236. package/dist/esm/reify/delete-nodes.d.ts.map +0 -1
  237. package/dist/esm/reify/delete-nodes.js.map +0 -1
  238. package/dist/esm/reify/extract-node.d.ts.map +0 -1
  239. package/dist/esm/reify/extract-node.js.map +0 -1
  240. package/dist/esm/reify/index.d.ts.map +0 -1
  241. package/dist/esm/reify/index.js.map +0 -1
  242. package/dist/esm/reify/internal-hoist.d.ts.map +0 -1
  243. package/dist/esm/reify/internal-hoist.js.map +0 -1
  244. package/dist/esm/reify/optional-fail.d.ts.map +0 -1
  245. package/dist/esm/reify/optional-fail.js.map +0 -1
  246. package/dist/esm/reify/rollback.d.ts.map +0 -1
  247. package/dist/esm/reify/rollback.js.map +0 -1
  248. package/dist/esm/reify/update-importers-package-json.d.ts.map +0 -1
  249. package/dist/esm/reify/update-importers-package-json.js.map +0 -1
  250. package/dist/esm/remove-optional-subgraph.d.ts.map +0 -1
  251. package/dist/esm/remove-optional-subgraph.js.map +0 -1
  252. package/dist/esm/resolve-save-type.d.ts.map +0 -1
  253. package/dist/esm/resolve-save-type.js.map +0 -1
  254. package/dist/esm/stringify-node.d.ts.map +0 -1
  255. package/dist/esm/stringify-node.js.map +0 -1
  256. package/dist/esm/transfer-data/load.d.ts.map +0 -1
  257. package/dist/esm/transfer-data/load.js.map +0 -1
  258. package/dist/esm/uninstall.d.ts.map +0 -1
  259. package/dist/esm/uninstall.js.map +0 -1
  260. package/dist/esm/update.d.ts.map +0 -1
  261. package/dist/esm/update.js.map +0 -1
  262. package/dist/esm/virtual-root.d.ts.map +0 -1
  263. package/dist/esm/virtual-root.js.map +0 -1
  264. package/dist/esm/visualization/human-readable-output.d.ts.map +0 -1
  265. package/dist/esm/visualization/human-readable-output.js.map +0 -1
  266. package/dist/esm/visualization/json-output.d.ts.map +0 -1
  267. package/dist/esm/visualization/json-output.js.map +0 -1
  268. package/dist/esm/visualization/mermaid-output.d.ts.map +0 -1
  269. package/dist/esm/visualization/mermaid-output.js.map +0 -1
  270. package/dist/esm/visualization/object-like-output.d.ts.map +0 -1
  271. package/dist/esm/visualization/object-like-output.js.map +0 -1
  272. /package/dist/{esm/actual → actual}/load.d.ts +0 -0
  273. /package/dist/{esm/browser.js → browser.js} +0 -0
  274. /package/dist/{esm/build.d.ts → build.d.ts} +0 -0
  275. /package/dist/{esm/build.js → build.js} +0 -0
  276. /package/dist/{esm/dependencies.d.ts → dependencies.d.ts} +0 -0
  277. /package/dist/{esm/dependencies.js → dependencies.js} +0 -0
  278. /package/dist/{esm/diff.js → diff.js} +0 -0
  279. /package/dist/{esm/ideal → ideal}/build.d.ts +0 -0
  280. /package/dist/{esm/ideal → ideal}/remove-satisfied-specs.d.ts +0 -0
  281. /package/dist/{esm/ideal → ideal}/remove-satisfied-specs.js +0 -0
  282. /package/dist/{esm/ideal → ideal}/types.js +0 -0
  283. /package/dist/{esm/lockfile → lockfile}/load-edges.d.ts +0 -0
  284. /package/dist/{esm/lockfile → lockfile}/types.d.ts +0 -0
  285. /package/dist/{esm/lockfile → lockfile}/types.js +0 -0
  286. /package/dist/{esm/modifiers.d.ts → modifiers.d.ts} +0 -0
  287. /package/dist/{esm/modifiers.js → modifiers.js} +0 -0
  288. /package/dist/{esm/non-empty-list.d.ts → non-empty-list.d.ts} +0 -0
  289. /package/dist/{esm/non-empty-list.js → non-empty-list.js} +0 -0
  290. /package/dist/{esm/reify → reify}/add-edge.d.ts +0 -0
  291. /package/dist/{esm/reify → reify}/add-edge.js +0 -0
  292. /package/dist/{esm/reify → reify}/add-nodes.d.ts +0 -0
  293. /package/dist/{esm/reify → reify}/add-nodes.js +0 -0
  294. /package/dist/{esm/reify → reify}/bin-chmod.d.ts +0 -0
  295. /package/dist/{esm/reify → reify}/bin-chmod.js +0 -0
  296. /package/dist/{esm/reify → reify}/build.d.ts +0 -0
  297. /package/dist/{esm/reify → reify}/calculate-save-value.d.ts +0 -0
  298. /package/dist/{esm/reify → reify}/calculate-save-value.js +0 -0
  299. /package/dist/{esm/reify → reify}/check-needed-build.d.ts +0 -0
  300. /package/dist/{esm/reify → reify}/check-needed-build.js +0 -0
  301. /package/dist/{esm/reify → reify}/delete-edge.d.ts +0 -0
  302. /package/dist/{esm/reify → reify}/delete-edge.js +0 -0
  303. /package/dist/{esm/reify → reify}/delete-edges.d.ts +0 -0
  304. /package/dist/{esm/reify → reify}/delete-edges.js +0 -0
  305. /package/dist/{esm/reify → reify}/delete-nodes.d.ts +0 -0
  306. /package/dist/{esm/reify → reify}/delete-nodes.js +0 -0
  307. /package/dist/{esm/reify → reify}/extract-node.d.ts +0 -0
  308. /package/dist/{esm/reify → reify}/index.d.ts +0 -0
  309. /package/dist/{esm/reify → reify}/internal-hoist.d.ts +0 -0
  310. /package/dist/{esm/reify → reify}/internal-hoist.js +0 -0
  311. /package/dist/{esm/reify → reify}/optional-fail.d.ts +0 -0
  312. /package/dist/{esm/reify → reify}/optional-fail.js +0 -0
  313. /package/dist/{esm/reify → reify}/rollback.d.ts +0 -0
  314. /package/dist/{esm/reify → reify}/rollback.js +0 -0
  315. /package/dist/{esm/remove-optional-subgraph.d.ts → remove-optional-subgraph.d.ts} +0 -0
  316. /package/dist/{esm/remove-optional-subgraph.js → remove-optional-subgraph.js} +0 -0
  317. /package/dist/{esm/resolve-save-type.d.ts → resolve-save-type.d.ts} +0 -0
  318. /package/dist/{esm/resolve-save-type.js → resolve-save-type.js} +0 -0
  319. /package/dist/{esm/stringify-node.d.ts → stringify-node.d.ts} +0 -0
  320. /package/dist/{esm/transfer-data → transfer-data}/load.d.ts +0 -0
  321. /package/dist/{esm/transfer-data → transfer-data}/load.js +0 -0
  322. /package/dist/{esm/uninstall.d.ts → uninstall.d.ts} +0 -0
  323. /package/dist/{esm/update.d.ts → update.d.ts} +0 -0
  324. /package/dist/{esm/virtual-root.d.ts → virtual-root.d.ts} +0 -0
  325. /package/dist/{esm/virtual-root.js → virtual-root.js} +0 -0
  326. /package/dist/{esm/visualization → visualization}/human-readable-output.d.ts +0 -0
  327. /package/dist/{esm/visualization → visualization}/mermaid-output.d.ts +0 -0
  328. /package/dist/{esm/visualization → visualization}/object-like-output.d.ts +0 -0
  329. /package/dist/{esm/visualization → visualization}/object-like-output.js +0 -0
@@ -0,0 +1,395 @@
1
+ import { joinDepIDTuple, joinExtra } from '@vltpkg/dep-id';
2
+ import { error } from '@vltpkg/error-cause';
3
+ import { Spec } from '@vltpkg/spec';
4
+ import { longDependencyTypes, normalizeManifest } from '@vltpkg/types';
5
+ import { fixupAddedNames } from "../fixup-added-names.js";
6
+ import { shorten } from "../dependencies.js";
7
+ import { removeOptionalSubgraph } from "../remove-optional-subgraph.js";
8
+ import { extractNode } from "../reify/extract-node.js";
9
+ import { endPeerPlacement, postPlacementPeerCheck, startPeerPlacement, } from "./peers.js";
10
+ /**
11
+ * Only install devDeps for git dependencies and importers
12
+ * Everything else always gets installed
13
+ */
14
+ const shouldInstallDepType = (node, depType) => depType !== 'devDependencies' ||
15
+ node.importer ||
16
+ node.id.startsWith('git');
17
+ /**
18
+ * Retrieve the {@link DepID} and location for a `file:` type {@link Node}.
19
+ */
20
+ const getFileTypeInfo = (spec, fromNode, scurry) => {
21
+ const f = spec.final;
22
+ if (f.type !== 'file')
23
+ return;
24
+ /* c8 ignore start - should be impossible */
25
+ if (!f.file) {
26
+ throw error('no path on file specifier', { spec });
27
+ }
28
+ /* c8 ignore stop */
29
+ // Given that both linked folders and local tarballs (both defined with
30
+ // usage of the `file:` spec prefix) location needs to be relative to their
31
+ // parents, build the expected path and use it for both location and id
32
+ const target = scurry.cwd.resolve(fromNode.location).resolve(f.file);
33
+ const path = target.relativePosix();
34
+ const id = joinDepIDTuple(['file', path]);
35
+ return {
36
+ path,
37
+ id,
38
+ isDirectory: !!target.lstatSync()?.isDirectory(),
39
+ };
40
+ };
41
+ const isStringArray = (a) => Array.isArray(a) && !a.some(b => typeof b !== 'string');
42
+ /**
43
+ * Fetch manifests for dependencies and create placement tasks.
44
+ */
45
+ const fetchManifestsForDeps = async (packageInfo, graph, fromNode, deps, scurry, peerContext, modifierRefs, depth = 0) => {
46
+ // Create fetch tasks for all dependencies at this level
47
+ const fetchTasks = [];
48
+ const placementTasks = [];
49
+ for (const { spec: originalSpec, type } of deps) {
50
+ let spec = originalSpec;
51
+ const fileTypeInfo = getFileTypeInfo(spec, fromNode, scurry);
52
+ const activeModifier = modifierRefs?.get(spec.name);
53
+ // here is the place we swap specs if a edge modifier was defined
54
+ const queryModifier = activeModifier?.modifier.query;
55
+ const completeModifier = activeModifier &&
56
+ activeModifier.interactiveBreadcrumb.current ===
57
+ activeModifier.modifier.breadcrumb.last;
58
+ if (queryModifier &&
59
+ completeModifier &&
60
+ 'spec' in activeModifier.modifier) {
61
+ spec = activeModifier.modifier.spec;
62
+ if (spec.bareSpec === '-') {
63
+ continue;
64
+ }
65
+ }
66
+ const peer = type === 'peer' || type === 'peerOptional';
67
+ // skip reusing nodes for peer deps since their reusability
68
+ // is handled ahead-of-time during its parent's placement
69
+ const existingNode = graph.findResolution(spec, fromNode, queryModifier);
70
+ // defines what nodes are eligible to be reused
71
+ const validExistingNode = existingNode &&
72
+ !existingNode.detached &&
73
+ // Regular deps can always reuse
74
+ /* c8 ignore start */
75
+ (!peer ||
76
+ // otherwise reusing peer deps only in case of a peerSetHash matche
77
+ existingNode.peerSetHash === fromNode.peerSetHash);
78
+ /* c8 ignore stop */
79
+ if (validExistingNode ||
80
+ // importers are handled at the ./add-nodes.ts top-level
81
+ // so we should just skip whenever we find one
82
+ existingNode?.importer) {
83
+ graph.addEdge(type, spec, fromNode, existingNode);
84
+ continue;
85
+ }
86
+ // is the current edge pointint go an optional dependency?
87
+ const edgeOptional = type === 'optional' || type === 'peerOptional';
88
+ // Start manifest fetch immediately for parallel processing
89
+ const manifestPromise =
90
+ // the "detached" node state means that it has already been load as
91
+ // part of a graph (either lockfile or actual) and it has valid manifest
92
+ // data so we shortcut the package info manifest fetch here
93
+ existingNode?.detached ?
94
+ Promise.resolve(existingNode.manifest)
95
+ // this is the entry point to fetch calls to retrieve manifests
96
+ // from the build ideal graph point of view
97
+ : packageInfo
98
+ .manifest(spec, { from: scurry.resolve(fromNode.location) })
99
+ .then(manifest => manifest)
100
+ .catch((er) => {
101
+ // optional deps ignored if inaccessible
102
+ if (edgeOptional || fromNode.optional) {
103
+ return undefined;
104
+ }
105
+ throw er;
106
+ });
107
+ const fetchTask = {
108
+ spec,
109
+ type,
110
+ fromNode,
111
+ fileTypeInfo,
112
+ activeModifier,
113
+ queryModifier,
114
+ edgeOptional,
115
+ manifestPromise,
116
+ depth,
117
+ peerContext,
118
+ };
119
+ fetchTasks.push(fetchTask);
120
+ }
121
+ // Create placement tasks from fetch tasks
122
+ for (const fetchTask of fetchTasks) {
123
+ const manifest = await fetchTask.manifestPromise;
124
+ placementTasks.push({
125
+ fetchTask,
126
+ manifest,
127
+ });
128
+ }
129
+ // sort placement tasks: non-peer dependencies first, then peer dependencies
130
+ // so that peer dependencies can easily reuse already placed regular
131
+ // dependencies as part of peer context set resolution also makes sure to
132
+ // sort by the manifest name for deterministic order.
133
+ placementTasks.sort((a, b) => {
134
+ const aIsPeer = (a.manifest?.peerDependencies &&
135
+ Object.keys(a.manifest.peerDependencies).length > 0) ?
136
+ 1
137
+ : 0;
138
+ const bIsPeer = (b.manifest?.peerDependencies &&
139
+ Object.keys(b.manifest.peerDependencies).length > 0) ?
140
+ 1
141
+ : 0;
142
+ // regular dependencies first, peer dependencies last
143
+ if (aIsPeer !== bIsPeer) {
144
+ return aIsPeer - bIsPeer;
145
+ }
146
+ // if both are in the same group,
147
+ // sort alphabetically by manifest name (fallback to spec.name)
148
+ const aName = a.manifest?.name /* c8 ignore next */ || a.fetchTask.spec.name;
149
+ const bName = b.manifest?.name || b.fetchTask.spec.name;
150
+ return aName.localeCompare(bName, 'en');
151
+ });
152
+ return placementTasks;
153
+ };
154
+ /**
155
+ * Process placement tasks and collect child dependencies, this is the
156
+ * second step of the appendNodes operation after manifest fetching in
157
+ * which the final graph data structure is actually built.
158
+ */
159
+ const processPlacementTasks = async (graph, options, placementTasks, add, modifiers, scurry, packageInfo, extractPromises, actual, seenExtracted, remover, transientAdd, transientRemove) => {
160
+ const childDepsToProcess = [];
161
+ for (const placementTask of placementTasks) {
162
+ const { fetchTask, manifest } = placementTask;
163
+ let { activeModifier, edgeOptional, fileTypeInfo, fromNode, peerContext, queryModifier, spec, type, } = fetchTask;
164
+ // fix the name in the `add` map when needed. This allows the upcoming
165
+ // reify step to properly update the package.json file dependencies
166
+ // using the correct names retrieved from the manifest data
167
+ const additiveMap = fromNode.importer ? add : transientAdd?.get(fromNode.id);
168
+ spec = fixupAddedNames(additiveMap, manifest, options, spec);
169
+ // handles missing manifest resolution
170
+ if (!manifest) {
171
+ if (!edgeOptional && fromNode.isOptional()) {
172
+ // failed resolution of a non-optional dep of an optional node
173
+ // have to clean up the dependents
174
+ removeOptionalSubgraph(graph, fromNode);
175
+ continue;
176
+ }
177
+ else if (edgeOptional) {
178
+ // failed resolution of an optional dep, just ignore it,
179
+ // nothing to prune because we never added it in the first place.
180
+ continue;
181
+ }
182
+ else {
183
+ throw error('failed to resolve dependency', {
184
+ spec,
185
+ from: fromNode.location,
186
+ });
187
+ }
188
+ }
189
+ // start peer deps placement process, populating the peer context with
190
+ // dependency data; adding the parent node deps and this manifest's
191
+ // peer deps references to the current peer context set
192
+ const peerPlacement = startPeerPlacement(peerContext, manifest, fromNode, options);
193
+ const peerSetHash = peerPlacement.peerSetHash;
194
+ const queuedEntries = peerPlacement.queuedEntries;
195
+ // places a new node in the graph representing a newly seen dependency
196
+ const node = graph.placePackage(fromNode, type, spec, normalizeManifest(manifest), fileTypeInfo?.id, joinExtra({ peerSetHash, modifier: queryModifier }));
197
+ /* c8 ignore start - not possible, already ensured manifest */
198
+ if (!node) {
199
+ throw error('failed to place package', {
200
+ from: fromNode.location,
201
+ spec,
202
+ });
203
+ }
204
+ /* c8 ignore stop */
205
+ // update the node modifier tracker
206
+ if (activeModifier) {
207
+ modifiers?.updateActiveEntry(node, activeModifier);
208
+ }
209
+ const eligibleForExtraction = type !== 'peer' &&
210
+ type !== 'peerOptional' &&
211
+ remover &&
212
+ extractPromises &&
213
+ actual &&
214
+ scurry &&
215
+ packageInfo &&
216
+ node.inVltStore() &&
217
+ !node.isOptional() &&
218
+ // this fixes an issue with installing `file:pathname` specs
219
+ /* c8 ignore next */ !fileTypeInfo?.isDirectory &&
220
+ !node.importer;
221
+ // extract the node if it meets the criteria for early extraction
222
+ if (eligibleForExtraction) {
223
+ /* c8 ignore start */
224
+ if (seenExtracted?.has(node.id)) {
225
+ continue;
226
+ }
227
+ /* c8 ignore stop */
228
+ seenExtracted?.add(node.id);
229
+ const actualNode = actual.nodes.get(node.id);
230
+ if (!actualNode?.equals(node)) {
231
+ // extract the node without awaiting - push the promise to the array
232
+ const extractPromise = extractNode(node, scurry, remover, options, packageInfo);
233
+ extractPromises.push(extractPromise);
234
+ }
235
+ }
236
+ // updates graph node information
237
+ if (fileTypeInfo?.path && fileTypeInfo.isDirectory) {
238
+ node.location = fileTypeInfo.path;
239
+ }
240
+ node.setResolved();
241
+ // collect child dependencies for processing in the next level
242
+ const nextPeerDeps = new Map();
243
+ // compute deps normally
244
+ const bundleDeps = manifest.bundleDependencies;
245
+ const bundled = new Set((node.id.startsWith('git') ||
246
+ node.importer ||
247
+ !isStringArray(bundleDeps)) ?
248
+ []
249
+ : bundleDeps);
250
+ // setup next level to process all child dependencies in the manifest
251
+ const nextDeps = [];
252
+ // traverse actual dependency declarations in the manifest
253
+ // creating dependency entries for them
254
+ for (const depTypeName of longDependencyTypes) {
255
+ const depRecord = manifest[depTypeName];
256
+ if (depRecord && shouldInstallDepType(node, depTypeName)) {
257
+ // Sort Object.entries for deterministic iteration
258
+ const sortedEntries = Object.entries(depRecord).sort(([a], [b]) => a.localeCompare(b, 'en'));
259
+ for (const [name, bareSpec] of sortedEntries) {
260
+ // might need to skip already placed peer deps here
261
+ if (bundled.has(name))
262
+ continue;
263
+ const dep = {
264
+ type: shorten(depTypeName, name, manifest),
265
+ spec: Spec.parse(name, bareSpec, {
266
+ ...options,
267
+ registry: spec.registry,
268
+ }),
269
+ };
270
+ if (depTypeName === 'peerDependencies') {
271
+ nextPeerDeps.set(name, dep);
272
+ }
273
+ else {
274
+ nextDeps.push(dep);
275
+ }
276
+ }
277
+ }
278
+ }
279
+ // Inject transient dependencies for non-importer nodes (nested folders)
280
+ // These are deps that were added from a nested folder context using
281
+ // relative file: specs that should resolve relative to that folder
282
+ const transientDeps = transientAdd?.get(node.id);
283
+ if (transientDeps) {
284
+ for (const [, dep] of transientDeps) {
285
+ if (dep.type === 'peer' || dep.type === 'peerOptional') {
286
+ nextPeerDeps.set(dep.spec.name, dep);
287
+ continue;
288
+ }
289
+ // remove the dependency from nextDeps if it already exists
290
+ const index = nextDeps.findIndex(d => d.spec.name === dep.spec.name);
291
+ if (index !== -1) {
292
+ nextDeps.splice(index, 1);
293
+ }
294
+ nextDeps.push(dep);
295
+ }
296
+ }
297
+ // Remove transient removals when needed
298
+ const transientRemovals = transientRemove?.get(node.id);
299
+ if (transientRemovals) {
300
+ for (const depName of transientRemovals) {
301
+ const index = nextDeps.findIndex(dep => dep.spec.name === depName);
302
+ if (index !== -1) {
303
+ nextDeps.splice(index, 1);
304
+ continue;
305
+ }
306
+ if (nextPeerDeps.has(depName)) {
307
+ nextPeerDeps.delete(depName);
308
+ }
309
+ }
310
+ }
311
+ // finish peer placement for this node, resolving satisfied peers
312
+ // to seen nodes from the peer context and adding unsatisfied peers
313
+ // to `nextDeps` so they get processed along regular dependencies
314
+ const updateContext = endPeerPlacement(peerContext, nextDeps, nextPeerDeps, graph, spec, fromNode, node, type, queuedEntries);
315
+ childDepsToProcess.push({
316
+ node,
317
+ deps: nextDeps,
318
+ modifierRefs: modifiers?.tryDependencies(node, nextDeps),
319
+ peerContext,
320
+ updateContext,
321
+ });
322
+ }
323
+ return childDepsToProcess;
324
+ };
325
+ /**
326
+ * Append new nodes in the given `graph` for dependencies specified at `add`
327
+ * and missing dependencies from the `deps` parameter.
328
+ *
329
+ * It also applies any modifiers that applies to a given node as it processes
330
+ * and builds the graph.
331
+ */
332
+ export const appendNodes = async (packageInfo, graph, fromNode, deps, scurry, options, seen, add, modifiers, modifierRefs, extractPromises, actual, seenExtracted, remover, transientAdd, transientRemove) => {
333
+ /* c8 ignore next */
334
+ if (seen.has(fromNode.id))
335
+ return;
336
+ seen.add(fromNode.id);
337
+ // Get the initial peer context from the graph
338
+ const [initialPeerContext] = graph.peerContexts;
339
+ /* c8 ignore start - impossible */
340
+ if (!initialPeerContext) {
341
+ throw error('no initial peer context found in graph');
342
+ }
343
+ /* c8 ignore stop */
344
+ // Use a queue for breadth-first processing
345
+ let currentLevelDeps = [
346
+ {
347
+ node: fromNode,
348
+ deps,
349
+ modifierRefs,
350
+ depth: 0,
351
+ peerContext: initialPeerContext,
352
+ /* c8 ignore start */
353
+ updateContext: {
354
+ putEntries: () => undefined,
355
+ resolvePeerDeps: () => { },
356
+ },
357
+ /* c8 ignore stop */
358
+ },
359
+ ];
360
+ while (currentLevelDeps.length > 0) {
361
+ const nextLevelDeps = [];
362
+ // Process all nodes at the current level in parallel
363
+ const levelResults = await Promise.all(currentLevelDeps.map(async ({ node, deps: nodeDeps, modifierRefs: nodeModifierRefs, peerContext, depth, }) => {
364
+ // Mark node as seen when we start processing its dependencies
365
+ seen.add(node.id);
366
+ // Fetch manifests for this node's dependencies
367
+ const placementTasks = await fetchManifestsForDeps(packageInfo, graph, node,
368
+ // Sort dependencies by spec.name for deterministic ordering
369
+ nodeDeps.sort((a, b) => a.spec.name.localeCompare(b.spec.name, 'en')), scurry, peerContext, nodeModifierRefs, depth);
370
+ // Process the placement tasks and get child dependencies
371
+ return await processPlacementTasks(graph, options, placementTasks, add, modifiers, scurry, packageInfo, extractPromises, actual, seenExtracted, remover, transientAdd, transientRemove);
372
+ }));
373
+ // Traverse the queued up children dependencies, adding and tracking
374
+ // dependencies on the peer context set, forking the context as needed
375
+ // and resolving any peer dependency that is able to be resolved using
376
+ // the current peer context set
377
+ postPlacementPeerCheck(graph, levelResults);
378
+ // Collect all child dependencies for the next level
379
+ for (const childDepsToProcess of levelResults) {
380
+ for (const childDep of childDepsToProcess) {
381
+ if (!seen.has(childDep.node.id)) {
382
+ /* c8 ignore next */
383
+ const currentDepth = currentLevelDeps[0]?.depth ?? 0;
384
+ nextLevelDeps.push({
385
+ ...childDep,
386
+ depth: currentDepth + 1,
387
+ });
388
+ }
389
+ }
390
+ }
391
+ // Move to the next level
392
+ currentLevelDeps = nextLevelDeps;
393
+ }
394
+ };
395
+ //# sourceMappingURL=append-nodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"append-nodes.js","sourceRoot":"","sources":["../../src/ideal/append-nodes.ts"],"names":[],"mappings":"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","sourcesContent":["import { joinDepIDTuple, joinExtra } from '@vltpkg/dep-id'\nimport type { DepID } from '@vltpkg/dep-id'\nimport { error } from '@vltpkg/error-cause'\nimport type { PackageInfoClient } from '@vltpkg/package-info'\nimport { Spec } from '@vltpkg/spec'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport { longDependencyTypes, normalizeManifest } from '@vltpkg/types'\nimport type {\n DependencyTypeLong,\n DependencySaveType,\n Manifest,\n} from '@vltpkg/types'\nimport type { PathScurry } from 'path-scurry'\nimport { fixupAddedNames } from '../fixup-added-names.ts'\nimport { shorten } from '../dependencies.ts'\nimport type { Dependency } from '../dependencies.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\nimport { removeOptionalSubgraph } from '../remove-optional-subgraph.ts'\nimport type {\n GraphModifier,\n ModifierActiveEntry,\n} from '../modifiers.ts'\nimport type { ExtractResult } from '../reify/extract-node.ts'\nimport { extractNode } from '../reify/extract-node.ts'\nimport type { RollbackRemove } from '@vltpkg/rollback-remove'\nimport {\n endPeerPlacement,\n postPlacementPeerCheck,\n startPeerPlacement,\n} from './peers.ts'\nimport type {\n PeerContext,\n AppendNodeEntry,\n ProcessPlacementResult,\n TransientAddMap,\n TransientRemoveMap,\n} from './types.ts'\n\ntype FileTypeInfo = {\n id: DepID\n path: string\n isDirectory: boolean\n}\n\n/**\n * Only install devDeps for git dependencies and importers\n * Everything else always gets installed\n */\nconst shouldInstallDepType = (\n node: Node,\n depType: DependencyTypeLong,\n) =>\n depType !== 'devDependencies' ||\n node.importer ||\n node.id.startsWith('git')\n\n/**\n * Retrieve the {@link DepID} and location for a `file:` type {@link Node}.\n */\nconst getFileTypeInfo = (\n spec: Spec,\n fromNode: Node,\n scurry: PathScurry,\n): FileTypeInfo | undefined => {\n const f = spec.final\n if (f.type !== 'file') return\n\n /* c8 ignore start - should be impossible */\n if (!f.file) {\n throw error('no path on file specifier', { spec })\n }\n /* c8 ignore stop */\n\n // Given that both linked folders and local tarballs (both defined with\n // usage of the `file:` spec prefix) location needs to be relative to their\n // parents, build the expected path and use it for both location and id\n const target = scurry.cwd.resolve(fromNode.location).resolve(f.file)\n const path = target.relativePosix()\n const id = joinDepIDTuple(['file', path])\n\n return {\n path,\n id,\n isDirectory: !!target.lstatSync()?.isDirectory(),\n }\n}\n\nconst isStringArray = (a: unknown): a is string[] =>\n Array.isArray(a) && !a.some(b => typeof b !== 'string')\n\n/**\n * Represents a manifest fetch operation with all the context needed.\n */\ntype ManifestFetchTask = {\n spec: Spec\n type: DependencySaveType\n fromNode: Node\n fileTypeInfo?: FileTypeInfo\n activeModifier?: ModifierActiveEntry\n queryModifier?: string\n edgeOptional: boolean\n manifestPromise: Promise<Manifest | undefined>\n depth: number\n peerContext: PeerContext\n}\n\n/**\n * Represents a node placement operation that depends on a resolved manifest.\n */\ntype NodePlacementTask = {\n fetchTask: ManifestFetchTask\n manifest: Manifest | undefined\n node?: Node\n childDeps?: Dependency[]\n childModifierRefs?: Map<string, ModifierActiveEntry>\n childPeerContext?: PeerContext\n}\n\n/**\n * Fetch manifests for dependencies and create placement tasks.\n */\nconst fetchManifestsForDeps = async (\n packageInfo: PackageInfoClient,\n graph: Graph,\n fromNode: Node,\n deps: Dependency[],\n scurry: PathScurry,\n peerContext: PeerContext,\n modifierRefs?: Map<string, ModifierActiveEntry>,\n depth = 0,\n): Promise<NodePlacementTask[]> => {\n // Create fetch tasks for all dependencies at this level\n const fetchTasks: ManifestFetchTask[] = []\n const placementTasks: NodePlacementTask[] = []\n\n for (const { spec: originalSpec, type } of deps) {\n let spec = originalSpec\n const fileTypeInfo = getFileTypeInfo(spec, fromNode, scurry)\n const activeModifier = modifierRefs?.get(spec.name)\n\n // here is the place we swap specs if a edge modifier was defined\n const queryModifier = activeModifier?.modifier.query\n const completeModifier =\n activeModifier &&\n activeModifier.interactiveBreadcrumb.current ===\n activeModifier.modifier.breadcrumb.last\n if (\n queryModifier &&\n completeModifier &&\n 'spec' in activeModifier.modifier\n ) {\n spec = activeModifier.modifier.spec\n if (spec.bareSpec === '-') {\n continue\n }\n }\n\n const peer = type === 'peer' || type === 'peerOptional'\n\n // skip reusing nodes for peer deps since their reusability\n // is handled ahead-of-time during its parent's placement\n const existingNode = graph.findResolution(\n spec,\n fromNode,\n queryModifier,\n )\n // defines what nodes are eligible to be reused\n const validExistingNode =\n existingNode &&\n !existingNode.detached &&\n // Regular deps can always reuse\n /* c8 ignore start */\n (!peer ||\n // otherwise reusing peer deps only in case of a peerSetHash matche\n existingNode.peerSetHash === fromNode.peerSetHash)\n /* c8 ignore stop */\n\n if (\n validExistingNode ||\n // importers are handled at the ./add-nodes.ts top-level\n // so we should just skip whenever we find one\n existingNode?.importer\n ) {\n graph.addEdge(type, spec, fromNode, existingNode)\n continue\n }\n\n // is the current edge pointint go an optional dependency?\n const edgeOptional =\n type === 'optional' || type === 'peerOptional'\n\n // Start manifest fetch immediately for parallel processing\n const manifestPromise =\n // the \"detached\" node state means that it has already been load as\n // part of a graph (either lockfile or actual) and it has valid manifest\n // data so we shortcut the package info manifest fetch here\n existingNode?.detached ?\n Promise.resolve(existingNode.manifest as Manifest | undefined)\n // this is the entry point to fetch calls to retrieve manifests\n // from the build ideal graph point of view\n : packageInfo\n .manifest(spec, { from: scurry.resolve(fromNode.location) })\n .then(manifest => manifest as Manifest | undefined)\n .catch((er: unknown) => {\n // optional deps ignored if inaccessible\n if (edgeOptional || fromNode.optional) {\n return undefined\n }\n throw er\n })\n\n const fetchTask: ManifestFetchTask = {\n spec,\n type,\n fromNode,\n fileTypeInfo,\n activeModifier,\n queryModifier,\n edgeOptional,\n manifestPromise,\n depth,\n peerContext,\n }\n\n fetchTasks.push(fetchTask)\n }\n\n // Create placement tasks from fetch tasks\n for (const fetchTask of fetchTasks) {\n const manifest = await fetchTask.manifestPromise\n\n placementTasks.push({\n fetchTask,\n manifest,\n })\n }\n\n // sort placement tasks: non-peer dependencies first, then peer dependencies\n // so that peer dependencies can easily reuse already placed regular\n // dependencies as part of peer context set resolution also makes sure to\n // sort by the manifest name for deterministic order.\n placementTasks.sort((a, b) => {\n const aIsPeer =\n (\n a.manifest?.peerDependencies &&\n Object.keys(a.manifest.peerDependencies).length > 0\n ) ?\n 1\n : 0\n const bIsPeer =\n (\n b.manifest?.peerDependencies &&\n Object.keys(b.manifest.peerDependencies).length > 0\n ) ?\n 1\n : 0\n\n // regular dependencies first, peer dependencies last\n if (aIsPeer !== bIsPeer) {\n return aIsPeer - bIsPeer\n }\n\n // if both are in the same group,\n // sort alphabetically by manifest name (fallback to spec.name)\n const aName =\n a.manifest?.name /* c8 ignore next */ || a.fetchTask.spec.name\n const bName = b.manifest?.name || b.fetchTask.spec.name\n return aName.localeCompare(bName, 'en')\n })\n\n return placementTasks\n}\n\n/**\n * Process placement tasks and collect child dependencies, this is the\n * second step of the appendNodes operation after manifest fetching in\n * which the final graph data structure is actually built.\n */\nconst processPlacementTasks = async (\n graph: Graph,\n options: SpecOptions,\n placementTasks: NodePlacementTask[],\n add?: Map<string, Dependency>,\n modifiers?: GraphModifier,\n scurry?: PathScurry,\n packageInfo?: PackageInfoClient,\n extractPromises?: Promise<ExtractResult>[],\n actual?: Graph,\n seenExtracted?: Set<DepID>,\n remover?: RollbackRemove,\n transientAdd?: TransientAddMap,\n transientRemove?: TransientRemoveMap,\n): Promise<ProcessPlacementResult> => {\n const childDepsToProcess: ProcessPlacementResult = []\n\n for (const placementTask of placementTasks) {\n const { fetchTask, manifest } = placementTask\n let {\n activeModifier,\n edgeOptional,\n fileTypeInfo,\n fromNode,\n peerContext,\n queryModifier,\n spec,\n type,\n } = fetchTask\n\n // fix the name in the `add` map when needed. This allows the upcoming\n // reify step to properly update the package.json file dependencies\n // using the correct names retrieved from the manifest data\n const additiveMap =\n fromNode.importer ? add : transientAdd?.get(fromNode.id)\n spec = fixupAddedNames(additiveMap, manifest, options, spec)\n\n // handles missing manifest resolution\n if (!manifest) {\n if (!edgeOptional && fromNode.isOptional()) {\n // failed resolution of a non-optional dep of an optional node\n // have to clean up the dependents\n removeOptionalSubgraph(graph, fromNode)\n continue\n } else if (edgeOptional) {\n // failed resolution of an optional dep, just ignore it,\n // nothing to prune because we never added it in the first place.\n continue\n } else {\n throw error('failed to resolve dependency', {\n spec,\n from: fromNode.location,\n })\n }\n }\n\n // start peer deps placement process, populating the peer context with\n // dependency data; adding the parent node deps and this manifest's\n // peer deps references to the current peer context set\n const peerPlacement = startPeerPlacement(\n peerContext,\n manifest,\n fromNode,\n options,\n )\n const peerSetHash = peerPlacement.peerSetHash\n const queuedEntries = peerPlacement.queuedEntries\n\n // places a new node in the graph representing a newly seen dependency\n const node = graph.placePackage(\n fromNode,\n type,\n spec,\n normalizeManifest(manifest),\n fileTypeInfo?.id,\n joinExtra({ peerSetHash, modifier: queryModifier }),\n )\n\n /* c8 ignore start - not possible, already ensured manifest */\n if (!node) {\n throw error('failed to place package', {\n from: fromNode.location,\n spec,\n })\n }\n /* c8 ignore stop */\n\n // update the node modifier tracker\n if (activeModifier) {\n modifiers?.updateActiveEntry(node, activeModifier)\n }\n\n const eligibleForExtraction =\n type !== 'peer' &&\n type !== 'peerOptional' &&\n remover &&\n extractPromises &&\n actual &&\n scurry &&\n packageInfo &&\n node.inVltStore() &&\n !node.isOptional() &&\n // this fixes an issue with installing `file:pathname` specs\n /* c8 ignore next */ !fileTypeInfo?.isDirectory &&\n !node.importer\n\n // extract the node if it meets the criteria for early extraction\n if (eligibleForExtraction) {\n /* c8 ignore start */\n if (seenExtracted?.has(node.id)) {\n continue\n }\n /* c8 ignore stop */\n seenExtracted?.add(node.id)\n const actualNode = actual.nodes.get(node.id)\n if (!actualNode?.equals(node)) {\n // extract the node without awaiting - push the promise to the array\n const extractPromise = extractNode(\n node,\n scurry,\n remover,\n options,\n packageInfo,\n )\n extractPromises.push(extractPromise)\n }\n }\n\n // updates graph node information\n if (fileTypeInfo?.path && fileTypeInfo.isDirectory) {\n node.location = fileTypeInfo.path\n }\n node.setResolved()\n\n // collect child dependencies for processing in the next level\n const nextPeerDeps = new Map<string, Dependency>()\n\n // compute deps normally\n const bundleDeps = manifest.bundleDependencies\n const bundled = new Set<string>(\n (\n node.id.startsWith('git') ||\n node.importer ||\n !isStringArray(bundleDeps)\n ) ?\n []\n : bundleDeps,\n )\n\n // setup next level to process all child dependencies in the manifest\n const nextDeps: Dependency[] = []\n\n // traverse actual dependency declarations in the manifest\n // creating dependency entries for them\n for (const depTypeName of longDependencyTypes) {\n const depRecord: Record<string, string> | undefined =\n manifest[depTypeName]\n\n if (depRecord && shouldInstallDepType(node, depTypeName)) {\n // Sort Object.entries for deterministic iteration\n const sortedEntries = Object.entries(depRecord).sort(\n ([a], [b]) => a.localeCompare(b, 'en'),\n )\n for (const [name, bareSpec] of sortedEntries) {\n // might need to skip already placed peer deps here\n if (bundled.has(name)) continue\n const dep = {\n type: shorten(depTypeName, name, manifest),\n spec: Spec.parse(name, bareSpec, {\n ...options,\n registry: spec.registry,\n }),\n }\n if (depTypeName === 'peerDependencies') {\n nextPeerDeps.set(name, dep)\n } else {\n nextDeps.push(dep)\n }\n }\n }\n }\n\n // Inject transient dependencies for non-importer nodes (nested folders)\n // These are deps that were added from a nested folder context using\n // relative file: specs that should resolve relative to that folder\n const transientDeps = transientAdd?.get(node.id)\n if (transientDeps) {\n for (const [, dep] of transientDeps) {\n if (dep.type === 'peer' || dep.type === 'peerOptional') {\n nextPeerDeps.set(dep.spec.name, dep)\n continue\n }\n\n // remove the dependency from nextDeps if it already exists\n const index = nextDeps.findIndex(\n d => d.spec.name === dep.spec.name,\n )\n if (index !== -1) {\n nextDeps.splice(index, 1)\n }\n\n nextDeps.push(dep)\n }\n }\n\n // Remove transient removals when needed\n const transientRemovals = transientRemove?.get(node.id)\n if (transientRemovals) {\n for (const depName of transientRemovals) {\n const index = nextDeps.findIndex(\n dep => dep.spec.name === depName,\n )\n if (index !== -1) {\n nextDeps.splice(index, 1)\n continue\n }\n\n if (nextPeerDeps.has(depName)) {\n nextPeerDeps.delete(depName)\n }\n }\n }\n\n // finish peer placement for this node, resolving satisfied peers\n // to seen nodes from the peer context and adding unsatisfied peers\n // to `nextDeps` so they get processed along regular dependencies\n const updateContext = endPeerPlacement(\n peerContext,\n nextDeps,\n nextPeerDeps,\n graph,\n spec,\n fromNode,\n node,\n type,\n queuedEntries,\n )\n\n childDepsToProcess.push({\n node,\n deps: nextDeps,\n modifierRefs: modifiers?.tryDependencies(node, nextDeps),\n peerContext,\n updateContext,\n })\n }\n\n return childDepsToProcess\n}\n\n/**\n * Append new nodes in the given `graph` for dependencies specified at `add`\n * and missing dependencies from the `deps` parameter.\n *\n * It also applies any modifiers that applies to a given node as it processes\n * and builds the graph.\n */\nexport const appendNodes = async (\n packageInfo: PackageInfoClient,\n graph: Graph,\n fromNode: Node,\n deps: Dependency[],\n scurry: PathScurry,\n options: SpecOptions,\n seen: Set<DepID>,\n add?: Map<string, Dependency>,\n modifiers?: GraphModifier,\n modifierRefs?: Map<string, ModifierActiveEntry>,\n extractPromises?: Promise<ExtractResult>[],\n actual?: Graph,\n seenExtracted?: Set<DepID>,\n remover?: RollbackRemove,\n transientAdd?: TransientAddMap,\n transientRemove?: TransientRemoveMap,\n) => {\n /* c8 ignore next */\n if (seen.has(fromNode.id)) return\n seen.add(fromNode.id)\n\n // Get the initial peer context from the graph\n const [initialPeerContext] = graph.peerContexts\n /* c8 ignore start - impossible */\n if (!initialPeerContext) {\n throw error('no initial peer context found in graph')\n }\n /* c8 ignore stop */\n\n // Use a queue for breadth-first processing\n let currentLevelDeps: AppendNodeEntry[] = [\n {\n node: fromNode,\n deps,\n modifierRefs,\n depth: 0,\n peerContext: initialPeerContext,\n /* c8 ignore start */\n updateContext: {\n putEntries: () => undefined,\n resolvePeerDeps: () => {},\n },\n /* c8 ignore stop */\n },\n ]\n\n while (currentLevelDeps.length > 0) {\n const nextLevelDeps: AppendNodeEntry[] = []\n\n // Process all nodes at the current level in parallel\n const levelResults = await Promise.all(\n currentLevelDeps.map(\n async ({\n node,\n deps: nodeDeps,\n modifierRefs: nodeModifierRefs,\n peerContext,\n depth,\n }: AppendNodeEntry) => {\n // Mark node as seen when we start processing its dependencies\n seen.add(node.id)\n\n // Fetch manifests for this node's dependencies\n const placementTasks = await fetchManifestsForDeps(\n packageInfo,\n graph,\n node,\n // Sort dependencies by spec.name for deterministic ordering\n nodeDeps.sort((a, b) =>\n a.spec.name.localeCompare(b.spec.name, 'en'),\n ),\n scurry,\n peerContext,\n nodeModifierRefs,\n depth,\n )\n\n // Process the placement tasks and get child dependencies\n return await processPlacementTasks(\n graph,\n options,\n placementTasks,\n add,\n modifiers,\n scurry,\n packageInfo,\n extractPromises,\n actual,\n seenExtracted,\n remover,\n transientAdd,\n transientRemove,\n )\n },\n ),\n )\n\n // Traverse the queued up children dependencies, adding and tracking\n // dependencies on the peer context set, forking the context as needed\n // and resolving any peer dependency that is able to be resolved using\n // the current peer context set\n postPlacementPeerCheck(graph, levelResults)\n\n // Collect all child dependencies for the next level\n for (const childDepsToProcess of levelResults) {\n for (const childDep of childDepsToProcess) {\n if (!seen.has(childDep.node.id)) {\n /* c8 ignore next */\n const currentDepth = currentLevelDeps[0]?.depth ?? 0\n nextLevelDeps.push({\n ...childDep,\n depth: currentDepth + 1,\n })\n }\n }\n }\n\n // Move to the next level\n currentLevelDeps = nextLevelDeps\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
+ import type { PackageJson } from '@vltpkg/package-json';
2
+ import type { RefreshIdealGraphOptions } from './refresh-ideal-graph.ts';
1
3
  import type { Graph } from '../graph.ts';
2
- import type { AddNodesOptions } from './add-nodes.ts';
3
- import type { RemoveNodesOptions } from './remove-nodes.ts';
4
- export type BuildIdealFromStartingGraphOptions = AddNodesOptions & RemoveNodesOptions & {
5
- projectRoot: string;
4
+ export type BuildIdealFromStartingGraphOptions = RefreshIdealGraphOptions & {
5
+ packageJson: PackageJson;
6
6
  };
7
7
  /**
8
8
  * Builds an ideal {@link Graph} representing the dependencies that
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-ideal-from-starting-graph.d.ts","sourceRoot":"","sources":["../../src/ideal/build-ideal-from-starting-graph.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAA;AACxE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC,MAAM,MAAM,kCAAkC,GAC5C,wBAAwB,GAAG;IACzB,WAAW,EAAE,WAAW,CAAA;CACzB,CAAA;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,YAC7B,kCAAkC,KAC1C,OAAO,CAAC,KAAK,CAmEf,CAAA"}
@@ -0,0 +1,70 @@
1
+ import { getImporterSpecs } from "./get-importer-specs.js";
2
+ import { refreshIdealGraph } from "./refresh-ideal-graph.js";
3
+ import { resolveSaveType } from "../resolve-save-type.js";
4
+ /**
5
+ * Builds an ideal {@link Graph} representing the dependencies that
6
+ * should be present in order to fulfill the requirements defined
7
+ * by the `package.json` and `vlt-lock.json` files using the `graph` set
8
+ * in options as a starting point. Also add / remove any dependencies
9
+ * listed in the `add` and `remove` properties.
10
+ */
11
+ export const buildIdealFromStartingGraph = async (options) => {
12
+ // Gets a map of dependencies that are keyed to its importer node ids,
13
+ // merging values already found in the graph with user specified values.
14
+ // Any dependencies that are already satisfied in the starting `graph`
15
+ // are going to be pruned from the resulting object.
16
+ const importerSpecs = getImporterSpecs(options);
17
+ // merge modifiedDependencies flags
18
+ options.add.modifiedDependencies =
19
+ options.add.modifiedDependencies ||
20
+ importerSpecs.add.modifiedDependencies;
21
+ options.remove.modifiedDependencies =
22
+ options.remove.modifiedDependencies ||
23
+ importerSpecs.remove.modifiedDependencies;
24
+ // merge values found on node specs with
25
+ // user-provided values from `options.add`
26
+ for (const [nodeId, deps] of importerSpecs.add) {
27
+ const node = options.graph.nodes.get(nodeId);
28
+ /* c8 ignore next - impossible */
29
+ if (!node)
30
+ continue;
31
+ if (!options.add.has(nodeId)) {
32
+ options.add.set(nodeId, deps);
33
+ continue;
34
+ }
35
+ // merge any deps found when reading the nodes manifest
36
+ // with the ones provided by the user in the `add` options,
37
+ // user-provided deps should take precedence
38
+ for (const [depName, dep] of deps) {
39
+ if (!options.add.get(nodeId)?.has(depName)) {
40
+ options.add.get(nodeId)?.set(depName, dep);
41
+ }
42
+ // update the save type for deps when using an implicit type
43
+ dep.type = resolveSaveType(node, depName, dep.type);
44
+ }
45
+ }
46
+ // merge values found on node specs with
47
+ // user-provided values from `options.remove`
48
+ for (const [nodeId, deps] of importerSpecs.remove) {
49
+ if (!options.remove.has(nodeId)) {
50
+ options.remove.set(nodeId, deps);
51
+ continue;
52
+ }
53
+ // merge any deps found when reading the nodes manifest
54
+ // with the ones provided by the user in the `remove` options
55
+ for (const depName of deps) {
56
+ options.remove.get(nodeId)?.add(depName);
57
+ }
58
+ }
59
+ // refreshs the current graph adding the nodes marked for addition
60
+ // and removing the ones marked for removal, while also recalculating
61
+ // peer dependencies and default locations
62
+ await refreshIdealGraph({
63
+ ...options,
64
+ transientAdd: importerSpecs.transientAdd,
65
+ transientRemove: importerSpecs.transientRemove,
66
+ });
67
+ options.graph.gc();
68
+ return options.graph;
69
+ };
70
+ //# sourceMappingURL=build-ideal-from-starting-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-ideal-from-starting-graph.js","sourceRoot":"","sources":["../../src/ideal/build-ideal-from-starting-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAUzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,EAC9C,OAA2C,EAC3B,EAAE;IAClB,sEAAsE;IACtE,wEAAwE;IACxE,sEAAsE;IACtE,oDAAoD;IACpD,MAAM,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAE/C,mCAAmC;IACnC,OAAO,CAAC,GAAG,CAAC,oBAAoB;QAC9B,OAAO,CAAC,GAAG,CAAC,oBAAoB;YAChC,aAAa,CAAC,GAAG,CAAC,oBAAoB,CAAA;IACxC,OAAO,CAAC,MAAM,CAAC,oBAAoB;QACjC,OAAO,CAAC,MAAM,CAAC,oBAAoB;YACnC,aAAa,CAAC,MAAM,CAAC,oBAAoB,CAAA;IAE3C,wCAAwC;IACxC,0CAA0C;IAC1C,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,aAAa,CAAC,GAAG,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAC5C,iCAAiC;QACjC,IAAI,CAAC,IAAI;YAAE,SAAQ;QAEnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YAC7B,SAAQ;QACV,CAAC;QAED,uDAAuD;QACvD,2DAA2D;QAC3D,4CAA4C;QAC5C,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;YAClC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;YAC5C,CAAC;YAED,4DAA4D;YAC5D,GAAG,CAAC,IAAI,GAAG,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;QACrD,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,6CAA6C;IAC7C,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC;QAClD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YAChC,SAAQ;QACV,CAAC;QAED,uDAAuD;QACvD,6DAA6D;QAC7D,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;QAC1C,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,qEAAqE;IACrE,0CAA0C;IAC1C,MAAM,iBAAiB,CAAC;QACtB,GAAG,OAAO;QACV,YAAY,EAAE,aAAa,CAAC,YAAY;QACxC,eAAe,EAAE,aAAa,CAAC,eAAe;KAC/C,CAAC,CAAA;IAEF,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,CAAA;IAElB,OAAO,OAAO,CAAC,KAAK,CAAA;AACtB,CAAC,CAAA","sourcesContent":["import { getImporterSpecs } from './get-importer-specs.ts'\nimport { refreshIdealGraph } from './refresh-ideal-graph.ts'\nimport { resolveSaveType } from '../resolve-save-type.ts'\nimport type { PackageJson } from '@vltpkg/package-json'\nimport type { RefreshIdealGraphOptions } from './refresh-ideal-graph.ts'\nimport type { Graph } from '../graph.ts'\n\nexport type BuildIdealFromStartingGraphOptions =\n RefreshIdealGraphOptions & {\n packageJson: PackageJson\n }\n\n/**\n * Builds an ideal {@link Graph} representing the dependencies that\n * should be present in order to fulfill the requirements defined\n * by the `package.json` and `vlt-lock.json` files using the `graph` set\n * in options as a starting point. Also add / remove any dependencies\n * listed in the `add` and `remove` properties.\n */\nexport const buildIdealFromStartingGraph = async (\n options: BuildIdealFromStartingGraphOptions,\n): Promise<Graph> => {\n // Gets a map of dependencies that are keyed to its importer node ids,\n // merging values already found in the graph with user specified values.\n // Any dependencies that are already satisfied in the starting `graph`\n // are going to be pruned from the resulting object.\n const importerSpecs = getImporterSpecs(options)\n\n // merge modifiedDependencies flags\n options.add.modifiedDependencies =\n options.add.modifiedDependencies ||\n importerSpecs.add.modifiedDependencies\n options.remove.modifiedDependencies =\n options.remove.modifiedDependencies ||\n importerSpecs.remove.modifiedDependencies\n\n // merge values found on node specs with\n // user-provided values from `options.add`\n for (const [nodeId, deps] of importerSpecs.add) {\n const node = options.graph.nodes.get(nodeId)\n /* c8 ignore next - impossible */\n if (!node) continue\n\n if (!options.add.has(nodeId)) {\n options.add.set(nodeId, deps)\n continue\n }\n\n // merge any deps found when reading the nodes manifest\n // with the ones provided by the user in the `add` options,\n // user-provided deps should take precedence\n for (const [depName, dep] of deps) {\n if (!options.add.get(nodeId)?.has(depName)) {\n options.add.get(nodeId)?.set(depName, dep)\n }\n\n // update the save type for deps when using an implicit type\n dep.type = resolveSaveType(node, depName, dep.type)\n }\n }\n\n // merge values found on node specs with\n // user-provided values from `options.remove`\n for (const [nodeId, deps] of importerSpecs.remove) {\n if (!options.remove.has(nodeId)) {\n options.remove.set(nodeId, deps)\n continue\n }\n\n // merge any deps found when reading the nodes manifest\n // with the ones provided by the user in the `remove` options\n for (const depName of deps) {\n options.remove.get(nodeId)?.add(depName)\n }\n }\n\n // refreshs the current graph adding the nodes marked for addition\n // and removing the ones marked for removal, while also recalculating\n // peer dependencies and default locations\n await refreshIdealGraph({\n ...options,\n transientAdd: importerSpecs.transientAdd,\n transientRemove: importerSpecs.transientRemove,\n })\n\n options.graph.gc()\n\n return options.graph\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/ideal/build.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,KAAK,EAAE,WAAW,IAAI,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,KAAK,EACV,2BAA2B,EAC3B,8BAA8B,EAE/B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAK7D,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,GAAG;IAClD;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,CAAA;IACd;;;;;OAKG;IACH,GAAG,CAAC,EAAE,2BAA2B,CAAA;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,8BAA8B,CAAA;IACvC;;OAEG;IACH,OAAO,EAAE,cAAc,CAAA;IACvB;;OAEG;IACH,WAAW,EAAE,iBAAiB,CAAA;CAC/B,CAAA;AAmBD;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,YACP,iBAAiB,KACzB,OAAO,CAAC,KAAK,CAgDf,CAAA"}
@@ -1,8 +1,23 @@
1
+ import { error } from '@vltpkg/error-cause';
1
2
  import { graphStep } from '@vltpkg/output';
2
3
  import { load as loadActual } from "../actual/load.js";
3
4
  import { load as loadVirtual } from "../lockfile/load.js";
4
5
  import { buildIdealFromStartingGraph } from "./build-ideal-from-starting-graph.js";
6
+ import { splitDepID } from '@vltpkg/dep-id';
5
7
  const getMap = (m) => m ?? new Map();
8
+ /**
9
+ * Validates that a file dependency node exists in the graph after
10
+ * a successful graph build. This helps providing an actionable error
11
+ * message in case the current working directory is a linked nested
12
+ * folder that hasn't yet been added as a dependency to an importer
13
+ * in the project.
14
+ */
15
+ const validateFileDepNode = (graph, id) => {
16
+ const [type, path] = splitDepID(id);
17
+ if (type === 'file' && !graph.nodes.get(id)) {
18
+ throw error('The current working dir is not a dependency of this project', { path });
19
+ }
20
+ };
6
21
  /**
7
22
  * Builds an ideal {@link Graph} representing the dependencies that
8
23
  * should be present in order to fulfill the requirements defined
@@ -22,7 +37,6 @@ export const build = async (options) => {
22
37
  ...options,
23
38
  mainManifest,
24
39
  monorepo,
25
- skipLoadingNodesOnModifiersChange: true,
26
40
  });
27
41
  }
28
42
  catch {
@@ -30,7 +44,6 @@ export const build = async (options) => {
30
44
  ...options,
31
45
  mainManifest,
32
46
  monorepo,
33
- skipLoadingNodesOnModifiersChange: true,
34
47
  });
35
48
  }
36
49
  const res = await buildIdealFromStartingGraph({
@@ -43,6 +56,20 @@ export const build = async (options) => {
43
56
  actual: options.actual,
44
57
  });
45
58
  done();
59
+ // when adding or removing a new dependency from a file dep,
60
+ // validate the receiver node was present in the graph
61
+ if (options.add) {
62
+ for (const [addKey, value] of options.add.entries()) {
63
+ if (value.size)
64
+ validateFileDepNode(res, addKey);
65
+ }
66
+ }
67
+ if (options.remove) {
68
+ for (const [removeKey, value] of options.remove.entries()) {
69
+ if (value.size)
70
+ validateFileDepNode(res, removeKey);
71
+ }
72
+ }
46
73
  return res;
47
74
  };
48
75
  //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/ideal/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EAAE,2BAA2B,EAAE,MAAM,sCAAsC,CAAA;AASlF,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAI3C,MAAM,MAAM,GAAG,CAA0B,CAAK,EAAE,EAAE,CAChD,CAAC,IAAK,IAAI,GAAG,EAAQ,CAAA;AA8BvB;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,CAAC,KAAY,EAAE,EAAS,EAAE,EAAE;IACtD,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC,CAAA;IACnC,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QAC5C,MAAM,KAAK,CACT,6DAA6D,EAC7D,EAAE,IAAI,EAAE,CACT,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EACxB,OAA0B,EACV,EAAE;IAClB,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;IAE/B,yDAAyD;IACzD,iDAAiD;IACjD,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IAC9D,MAAM,YAAY,GAChB,OAAO,CAAC,YAAY,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAC/D,IAAI,KAAK,CAAA;IACT,IAAI,CAAC;QACH,KAAK,GAAG,WAAW,CAAC;YAClB,GAAG,OAAO;YACV,YAAY;YACZ,QAAQ;SACT,CAAC,CAAA;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,GAAG,UAAU,CAAC;YACjB,GAAG,OAAO;YACV,YAAY;YACZ,QAAQ;SACT,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,2BAA2B,CAAC;QAC5C,GAAG,OAAO;QACV,MAAM;QACN,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;QACxB,KAAK;QACL,WAAW;QACX,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAA;IACF,IAAI,EAAE,CAAA;IAEN,4DAA4D;IAC5D,sDAAsD;IACtD,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,IAAI,KAAK,CAAC,IAAI;gBAAE,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QAClD,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YAC1D,IAAI,KAAK,CAAC,IAAI;gBAAE,mBAAmB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;QACrD,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport { graphStep } from '@vltpkg/output'\nimport { load as loadActual } from '../actual/load.ts'\nimport { load as loadVirtual } from '../lockfile/load.ts'\nimport { buildIdealFromStartingGraph } from './build-ideal-from-starting-graph.ts'\nimport type { PackageInfoClient } from '@vltpkg/package-info'\nimport type { LoadOptions as LoadActualOptions } from '../actual/load.ts'\nimport type {\n AddImportersDependenciesMap,\n RemoveImportersDependenciesMap,\n Dependency,\n} from '../dependencies.ts'\nimport type { Graph } from '../graph.ts'\nimport { splitDepID } from '@vltpkg/dep-id'\nimport type { DepID } from '@vltpkg/dep-id'\nimport type { RollbackRemove } from '@vltpkg/rollback-remove'\n\nconst getMap = <T extends Map<any, any>>(m?: T) =>\n m ?? (new Map() as T)\n\nexport type BuildIdealOptions = LoadActualOptions & {\n /**\n * An actual graph\n */\n actual?: Graph\n /**\n * A `Map` in which keys are {@link DepID} linking to another `Map` in which\n * keys are the dependency names and values are {@link Dependency}. This\n * structure represents dependencies that need to be added to the importer\n * represented by {@link DepID}.\n */\n add?: AddImportersDependenciesMap\n /**\n * A `Map` object representing nodes to be removed from the ideal graph.\n * Each {@link DepID} key represents an importer node and the `Set` of\n * dependency names to be removed from its dependency list.\n */\n remove?: RemoveImportersDependenciesMap\n /**\n * A {@link RollbackRemove} instance to handle extraction rollbacks\n */\n remover: RollbackRemove\n /**\n * A {@link PackageInfoClient} instance to read manifest info from.\n */\n packageInfo: PackageInfoClient\n}\n\n/**\n * Validates that a file dependency node exists in the graph after\n * a successful graph build. This helps providing an actionable error\n * message in case the current working directory is a linked nested\n * folder that hasn't yet been added as a dependency to an importer\n * in the project.\n */\nconst validateFileDepNode = (graph: Graph, id: DepID) => {\n const [type, path] = splitDepID(id)\n if (type === 'file' && !graph.nodes.get(id)) {\n throw error(\n 'The current working dir is not a dependency of this project',\n { path },\n )\n }\n}\n\n/**\n * Builds an ideal {@link Graph} representing the dependencies that\n * should be present in order to fulfill the requirements defined\n * by the `package.json` and `vlt-lock.json` files using either the\n * virtual or actual graph as a starting point. Also add / remove any\n * dependencies listed in the `add` and `remove` properties.\n */\nexport const build = async (\n options: BuildIdealOptions,\n): Promise<Graph> => {\n const done = graphStep('build')\n\n // Creates the shared instances that are going to be used\n // in both the loader methods and the build graph\n const { packageInfo, packageJson, scurry, monorepo } = options\n const mainManifest =\n options.mainManifest ?? packageJson.read(options.projectRoot)\n let graph\n try {\n graph = loadVirtual({\n ...options,\n mainManifest,\n monorepo,\n })\n } catch {\n graph = loadActual({\n ...options,\n mainManifest,\n monorepo,\n })\n }\n\n const res = await buildIdealFromStartingGraph({\n ...options,\n scurry,\n add: getMap(options.add),\n graph,\n packageInfo,\n remove: getMap(options.remove),\n actual: options.actual,\n })\n done()\n\n // when adding or removing a new dependency from a file dep,\n // validate the receiver node was present in the graph\n if (options.add) {\n for (const [addKey, value] of options.add.entries()) {\n if (value.size) validateFileDepNode(res, addKey)\n }\n }\n if (options.remove) {\n for (const [removeKey, value] of options.remove.entries()) {\n if (value.size) validateFileDepNode(res, removeKey)\n }\n }\n\n return res\n}\n"]}