ohrisk 0.127.1 → 0.129.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -7824,11 +7824,11 @@ var require_lockfile = __commonJS((exports, module) => {
7824
7824
  };
7825
7825
  })();
7826
7826
  let getEolFromFile = (() => {
7827
- var _ref30 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (path6) {
7828
- if (!(yield exists(path6))) {
7827
+ var _ref30 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (path7) {
7828
+ if (!(yield exists(path7))) {
7829
7829
  return;
7830
7830
  }
7831
- const buffer = yield readFileBuffer(path6);
7831
+ const buffer = yield readFileBuffer(path7);
7832
7832
  for (let i = 0;i < buffer.length; ++i) {
7833
7833
  if (buffer[i] === cr) {
7834
7834
  return `\r
@@ -7846,13 +7846,13 @@ var require_lockfile = __commonJS((exports, module) => {
7846
7846
  };
7847
7847
  })();
7848
7848
  let writeFilePreservingEol = exports2.writeFilePreservingEol = (() => {
7849
- var _ref31 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (path6, data) {
7850
- const eol = (yield getEolFromFile(path6)) || (_os || _load_os()).default.EOL;
7849
+ var _ref31 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (path7, data) {
7850
+ const eol = (yield getEolFromFile(path7)) || (_os || _load_os()).default.EOL;
7851
7851
  if (eol !== `
7852
7852
  `) {
7853
7853
  data = data.replace(/\n/g, eol);
7854
7854
  }
7855
- yield writeFile(path6, data);
7855
+ yield writeFile(path7, data);
7856
7856
  });
7857
7857
  return function writeFilePreservingEol2(_x30, _x31) {
7858
7858
  return _ref31.apply(this, arguments);
@@ -7903,10 +7903,10 @@ var require_lockfile = __commonJS((exports, module) => {
7903
7903
  break;
7904
7904
  _ref35 = _i15.value;
7905
7905
  }
7906
- const path6 = _ref35;
7906
+ const path7 = _ref35;
7907
7907
  try {
7908
- const fd = yield open(path6, "r");
7909
- return (_fs || _load_fs()).default.createReadStream(path6, { fd });
7908
+ const fd = yield open(path7, "r");
7909
+ return (_fs || _load_fs()).default.createReadStream(path7, { fd });
7910
7910
  } catch (err2) {}
7911
7911
  }
7912
7912
  return null;
@@ -8070,7 +8070,7 @@ var require_lockfile = __commonJS((exports, module) => {
8070
8070
  });
8071
8071
  exports2.getPathKey = getPathKey;
8072
8072
  const os = __webpack_require__(36);
8073
- const path6 = __webpack_require__(0);
8073
+ const path7 = __webpack_require__(0);
8074
8074
  const userHome = __webpack_require__(45).default;
8075
8075
  var _require = __webpack_require__(171);
8076
8076
  const { getCacheDir, getConfigDir, getDataDir } = _require;
@@ -8093,29 +8093,29 @@ var require_lockfile = __commonJS((exports, module) => {
8093
8093
  function getPreferredCacheDirectories() {
8094
8094
  const preferredCacheDirectories = [getCacheDir()];
8095
8095
  if (process.getuid) {
8096
- preferredCacheDirectories.push(path6.join(os.tmpdir(), `.yarn-cache-${process.getuid()}`));
8096
+ preferredCacheDirectories.push(path7.join(os.tmpdir(), `.yarn-cache-${process.getuid()}`));
8097
8097
  }
8098
- preferredCacheDirectories.push(path6.join(os.tmpdir(), `.yarn-cache`));
8098
+ preferredCacheDirectories.push(path7.join(os.tmpdir(), `.yarn-cache`));
8099
8099
  return preferredCacheDirectories;
8100
8100
  }
8101
8101
  const PREFERRED_MODULE_CACHE_DIRECTORIES = exports2.PREFERRED_MODULE_CACHE_DIRECTORIES = getPreferredCacheDirectories();
8102
8102
  const CONFIG_DIRECTORY = exports2.CONFIG_DIRECTORY = getConfigDir();
8103
8103
  const DATA_DIRECTORY = exports2.DATA_DIRECTORY = getDataDir();
8104
- const LINK_REGISTRY_DIRECTORY = exports2.LINK_REGISTRY_DIRECTORY = path6.join(DATA_DIRECTORY, "link");
8105
- const GLOBAL_MODULE_DIRECTORY = exports2.GLOBAL_MODULE_DIRECTORY = path6.join(DATA_DIRECTORY, "global");
8104
+ const LINK_REGISTRY_DIRECTORY = exports2.LINK_REGISTRY_DIRECTORY = path7.join(DATA_DIRECTORY, "link");
8105
+ const GLOBAL_MODULE_DIRECTORY = exports2.GLOBAL_MODULE_DIRECTORY = path7.join(DATA_DIRECTORY, "global");
8106
8106
  const NODE_BIN_PATH = exports2.NODE_BIN_PATH = process.execPath;
8107
8107
  const YARN_BIN_PATH = exports2.YARN_BIN_PATH = getYarnBinPath();
8108
8108
  function getYarnBinPath() {
8109
8109
  if (isWebpackBundle) {
8110
8110
  return __filename;
8111
8111
  } else {
8112
- return path6.join(__dirname, "..", "bin", "yarn.js");
8112
+ return path7.join(__dirname, "..", "bin", "yarn.js");
8113
8113
  }
8114
8114
  }
8115
8115
  const NODE_MODULES_FOLDER = exports2.NODE_MODULES_FOLDER = "node_modules";
8116
8116
  const NODE_PACKAGE_JSON = exports2.NODE_PACKAGE_JSON = "package.json";
8117
8117
  const POSIX_GLOBAL_PREFIX = exports2.POSIX_GLOBAL_PREFIX = `${process.env.DESTDIR || ""}/usr/local`;
8118
- const FALLBACK_GLOBAL_PREFIX = exports2.FALLBACK_GLOBAL_PREFIX = path6.join(userHome, ".yarn");
8118
+ const FALLBACK_GLOBAL_PREFIX = exports2.FALLBACK_GLOBAL_PREFIX = path7.join(userHome, ".yarn");
8119
8119
  const META_FOLDER = exports2.META_FOLDER = ".yarn-meta";
8120
8120
  const INTEGRITY_FILENAME = exports2.INTEGRITY_FILENAME = ".yarn-integrity";
8121
8121
  const LOCKFILE_FILENAME = exports2.LOCKFILE_FILENAME = "yarn.lock";
@@ -8349,7 +8349,7 @@ var require_lockfile = __commonJS((exports, module) => {
8349
8349
  return obj && obj.__esModule ? obj : { default: obj };
8350
8350
  }
8351
8351
  const invariant = __webpack_require__(7);
8352
- const path6 = __webpack_require__(0);
8352
+ const path7 = __webpack_require__(0);
8353
8353
  const ssri = __webpack_require__(55);
8354
8354
  function getName(pattern) {
8355
8355
  return (0, (_normalizePattern || _load_normalizePattern()).normalizePattern)(pattern).name;
@@ -8415,7 +8415,7 @@ var require_lockfile = __commonJS((exports, module) => {
8415
8415
  }
8416
8416
  static fromDirectory(dir, reporter) {
8417
8417
  return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
8418
- const lockfileLoc = path6.join(dir, (_constants || _load_constants()).LOCKFILE_FILENAME);
8418
+ const lockfileLoc = path7.join(dir, (_constants || _load_constants()).LOCKFILE_FILENAME);
8419
8419
  let lockfile;
8420
8420
  let rawLockfile = "";
8421
8421
  let parseResult;
@@ -8834,9 +8834,9 @@ var require_lockfile = __commonJS((exports, module) => {
8834
8834
  function _interopRequireDefault(obj) {
8835
8835
  return obj && obj.__esModule ? obj : { default: obj };
8836
8836
  }
8837
- const path6 = __webpack_require__(0);
8837
+ const path7 = __webpack_require__(0);
8838
8838
  const home = exports2.home = __webpack_require__(36).homedir();
8839
- const userHomeDir = (_rootUser || _load_rootUser()).default ? path6.resolve("/usr/local/share") : home;
8839
+ const userHomeDir = (_rootUser || _load_rootUser()).default ? path7.resolve("/usr/local/share") : home;
8840
8840
  exports2.default = userHomeDir;
8841
8841
  },
8842
8842
  function(module2, exports2) {
@@ -9236,9 +9236,9 @@ var require_lockfile = __commonJS((exports, module) => {
9236
9236
  function(module2, exports2, __webpack_require__) {
9237
9237
  module2.exports = minimatch;
9238
9238
  minimatch.Minimatch = Minimatch;
9239
- var path6 = { sep: "/" };
9239
+ var path7 = { sep: "/" };
9240
9240
  try {
9241
- path6 = __webpack_require__(0);
9241
+ path7 = __webpack_require__(0);
9242
9242
  } catch (er) {}
9243
9243
  var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {};
9244
9244
  var expand = __webpack_require__(175);
@@ -9320,8 +9320,8 @@ var require_lockfile = __commonJS((exports, module) => {
9320
9320
  if (!options)
9321
9321
  options = {};
9322
9322
  pattern = pattern.trim();
9323
- if (path6.sep !== "/") {
9324
- pattern = pattern.split(path6.sep).join("/");
9323
+ if (path7.sep !== "/") {
9324
+ pattern = pattern.split(path7.sep).join("/");
9325
9325
  }
9326
9326
  this.options = options;
9327
9327
  this.set = [];
@@ -9688,8 +9688,8 @@ var require_lockfile = __commonJS((exports, module) => {
9688
9688
  if (f === "/" && partial)
9689
9689
  return true;
9690
9690
  var options = this.options;
9691
- if (path6.sep !== "/") {
9692
- f = f.split(path6.sep).join("/");
9691
+ if (path7.sep !== "/") {
9692
+ f = f.split(path7.sep).join("/");
9693
9693
  }
9694
9694
  f = f.split(slashSplit);
9695
9695
  this.debug(this.pattern, "split", f);
@@ -9919,7 +9919,7 @@ globstar while`, file, fr, pattern, pr, swallowee);
9919
9919
  var Minimatch = minimatch.Minimatch;
9920
9920
  var inherits = __webpack_require__(42);
9921
9921
  var EE = __webpack_require__(54).EventEmitter;
9922
- var path6 = __webpack_require__(0);
9922
+ var path7 = __webpack_require__(0);
9923
9923
  var assert = __webpack_require__(22);
9924
9924
  var isAbsolute = __webpack_require__(76);
9925
9925
  var globSync = __webpack_require__(218);
@@ -10202,7 +10202,7 @@ globstar while`, file, fr, pattern, pr, swallowee);
10202
10202
  e = prefix + e;
10203
10203
  }
10204
10204
  if (e.charAt(0) === "/" && !this.nomount) {
10205
- e = path6.join(this.root, e);
10205
+ e = path7.join(this.root, e);
10206
10206
  }
10207
10207
  this._emitMatch(index, e);
10208
10208
  }
@@ -10389,9 +10389,9 @@ globstar while`, file, fr, pattern, pr, swallowee);
10389
10389
  if (prefix && isAbsolute(prefix) && !this.nomount) {
10390
10390
  var trail = /[\/\\]$/.test(prefix);
10391
10391
  if (prefix.charAt(0) === "/") {
10392
- prefix = path6.join(this.root, prefix);
10392
+ prefix = path7.join(this.root, prefix);
10393
10393
  } else {
10394
- prefix = path6.resolve(this.root, prefix);
10394
+ prefix = path7.resolve(this.root, prefix);
10395
10395
  if (trail)
10396
10396
  prefix += "/";
10397
10397
  }
@@ -10464,12 +10464,12 @@ globstar while`, file, fr, pattern, pr, swallowee);
10464
10464
  };
10465
10465
  },
10466
10466
  function(module2, exports2, __webpack_require__) {
10467
- function posix(path6) {
10468
- return path6.charAt(0) === "/";
10467
+ function posix(path7) {
10468
+ return path7.charAt(0) === "/";
10469
10469
  }
10470
- function win32(path6) {
10470
+ function win32(path7) {
10471
10471
  var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
10472
- var result = splitDeviceRe.exec(path6);
10472
+ var result = splitDeviceRe.exec(path7);
10473
10473
  var device = result[1] || "";
10474
10474
  var isUnc = Boolean(device && device.charAt(1) !== ":");
10475
10475
  return Boolean(result[2] || isUnc);
@@ -11430,7 +11430,7 @@ globstar while`, file, fr, pattern, pr, swallowee);
11430
11430
  function ownProp(obj, field) {
11431
11431
  return Object.prototype.hasOwnProperty.call(obj, field);
11432
11432
  }
11433
- var path6 = __webpack_require__(0);
11433
+ var path7 = __webpack_require__(0);
11434
11434
  var minimatch = __webpack_require__(60);
11435
11435
  var isAbsolute = __webpack_require__(76);
11436
11436
  var Minimatch = minimatch.Minimatch;
@@ -11497,11 +11497,11 @@ globstar while`, file, fr, pattern, pr, swallowee);
11497
11497
  if (!ownProp(options, "cwd"))
11498
11498
  self2.cwd = cwd;
11499
11499
  else {
11500
- self2.cwd = path6.resolve(options.cwd);
11500
+ self2.cwd = path7.resolve(options.cwd);
11501
11501
  self2.changedCwd = self2.cwd !== cwd;
11502
11502
  }
11503
- self2.root = options.root || path6.resolve(self2.cwd, "/");
11504
- self2.root = path6.resolve(self2.root);
11503
+ self2.root = options.root || path7.resolve(self2.cwd, "/");
11504
+ self2.root = path7.resolve(self2.root);
11505
11505
  if (process.platform === "win32")
11506
11506
  self2.root = self2.root.replace(/\\/g, "/");
11507
11507
  self2.cwdAbs = isAbsolute(self2.cwd) ? self2.cwd : makeAbs(self2, self2.cwd);
@@ -11582,35 +11582,35 @@ globstar while`, file, fr, pattern, pr, swallowee);
11582
11582
  function makeAbs(self2, f) {
11583
11583
  var abs = f;
11584
11584
  if (f.charAt(0) === "/") {
11585
- abs = path6.join(self2.root, f);
11585
+ abs = path7.join(self2.root, f);
11586
11586
  } else if (isAbsolute(f) || f === "") {
11587
11587
  abs = f;
11588
11588
  } else if (self2.changedCwd) {
11589
- abs = path6.resolve(self2.cwd, f);
11589
+ abs = path7.resolve(self2.cwd, f);
11590
11590
  } else {
11591
- abs = path6.resolve(f);
11591
+ abs = path7.resolve(f);
11592
11592
  }
11593
11593
  if (process.platform === "win32")
11594
11594
  abs = abs.replace(/\\/g, "/");
11595
11595
  return abs;
11596
11596
  }
11597
- function isIgnored(self2, path7) {
11597
+ function isIgnored(self2, path8) {
11598
11598
  if (!self2.ignore.length)
11599
11599
  return false;
11600
11600
  return self2.ignore.some(function(item) {
11601
- return item.matcher.match(path7) || !!(item.gmatcher && item.gmatcher.match(path7));
11601
+ return item.matcher.match(path8) || !!(item.gmatcher && item.gmatcher.match(path8));
11602
11602
  });
11603
11603
  }
11604
- function childrenIgnored(self2, path7) {
11604
+ function childrenIgnored(self2, path8) {
11605
11605
  if (!self2.ignore.length)
11606
11606
  return false;
11607
11607
  return self2.ignore.some(function(item) {
11608
- return !!(item.gmatcher && item.gmatcher.match(path7));
11608
+ return !!(item.gmatcher && item.gmatcher.match(path8));
11609
11609
  });
11610
11610
  }
11611
11611
  },
11612
11612
  function(module2, exports2, __webpack_require__) {
11613
- var path6 = __webpack_require__(0);
11613
+ var path7 = __webpack_require__(0);
11614
11614
  var fs = __webpack_require__(3);
11615
11615
  var _0777 = parseInt("0777", 8);
11616
11616
  module2.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
@@ -11629,7 +11629,7 @@ globstar while`, file, fr, pattern, pr, swallowee);
11629
11629
  if (!made)
11630
11630
  made = null;
11631
11631
  var cb = f || function() {};
11632
- p = path6.resolve(p);
11632
+ p = path7.resolve(p);
11633
11633
  xfs.mkdir(p, mode, function(er) {
11634
11634
  if (!er) {
11635
11635
  made = made || p;
@@ -11637,7 +11637,7 @@ globstar while`, file, fr, pattern, pr, swallowee);
11637
11637
  }
11638
11638
  switch (er.code) {
11639
11639
  case "ENOENT":
11640
- mkdirP(path6.dirname(p), opts, function(er2, made2) {
11640
+ mkdirP(path7.dirname(p), opts, function(er2, made2) {
11641
11641
  if (er2)
11642
11642
  cb(er2, made2);
11643
11643
  else
@@ -11666,14 +11666,14 @@ globstar while`, file, fr, pattern, pr, swallowee);
11666
11666
  }
11667
11667
  if (!made)
11668
11668
  made = null;
11669
- p = path6.resolve(p);
11669
+ p = path7.resolve(p);
11670
11670
  try {
11671
11671
  xfs.mkdirSync(p, mode);
11672
11672
  made = made || p;
11673
11673
  } catch (err0) {
11674
11674
  switch (err0.code) {
11675
11675
  case "ENOENT":
11676
- made = sync(path6.dirname(p), opts, made);
11676
+ made = sync(path7.dirname(p), opts, made);
11677
11677
  sync(p, opts, made);
11678
11678
  break;
11679
11679
  default:
@@ -12051,27 +12051,27 @@ ${indent}`);
12051
12051
  exports2.getDataDir = getDataDir;
12052
12052
  exports2.getCacheDir = getCacheDir;
12053
12053
  exports2.getConfigDir = getConfigDir;
12054
- const path6 = __webpack_require__(0);
12054
+ const path7 = __webpack_require__(0);
12055
12055
  const userHome = __webpack_require__(45).default;
12056
- const FALLBACK_CONFIG_DIR = path6.join(userHome, ".config", "yarn");
12057
- const FALLBACK_CACHE_DIR = path6.join(userHome, ".cache", "yarn");
12056
+ const FALLBACK_CONFIG_DIR = path7.join(userHome, ".config", "yarn");
12057
+ const FALLBACK_CACHE_DIR = path7.join(userHome, ".cache", "yarn");
12058
12058
  function getDataDir() {
12059
12059
  if (process.platform === "win32") {
12060
12060
  const WIN32_APPDATA_DIR = getLocalAppDataDir();
12061
- return WIN32_APPDATA_DIR == null ? FALLBACK_CONFIG_DIR : path6.join(WIN32_APPDATA_DIR, "Data");
12061
+ return WIN32_APPDATA_DIR == null ? FALLBACK_CONFIG_DIR : path7.join(WIN32_APPDATA_DIR, "Data");
12062
12062
  } else if (process.env.XDG_DATA_HOME) {
12063
- return path6.join(process.env.XDG_DATA_HOME, "yarn");
12063
+ return path7.join(process.env.XDG_DATA_HOME, "yarn");
12064
12064
  } else {
12065
12065
  return FALLBACK_CONFIG_DIR;
12066
12066
  }
12067
12067
  }
12068
12068
  function getCacheDir() {
12069
12069
  if (process.platform === "win32") {
12070
- return path6.join(getLocalAppDataDir() || path6.join(userHome, "AppData", "Local", "Yarn"), "Cache");
12070
+ return path7.join(getLocalAppDataDir() || path7.join(userHome, "AppData", "Local", "Yarn"), "Cache");
12071
12071
  } else if (process.env.XDG_CACHE_HOME) {
12072
- return path6.join(process.env.XDG_CACHE_HOME, "yarn");
12072
+ return path7.join(process.env.XDG_CACHE_HOME, "yarn");
12073
12073
  } else if (process.platform === "darwin") {
12074
- return path6.join(userHome, "Library", "Caches", "Yarn");
12074
+ return path7.join(userHome, "Library", "Caches", "Yarn");
12075
12075
  } else {
12076
12076
  return FALLBACK_CACHE_DIR;
12077
12077
  }
@@ -12079,15 +12079,15 @@ ${indent}`);
12079
12079
  function getConfigDir() {
12080
12080
  if (process.platform === "win32") {
12081
12081
  const WIN32_APPDATA_DIR = getLocalAppDataDir();
12082
- return WIN32_APPDATA_DIR == null ? FALLBACK_CONFIG_DIR : path6.join(WIN32_APPDATA_DIR, "Config");
12082
+ return WIN32_APPDATA_DIR == null ? FALLBACK_CONFIG_DIR : path7.join(WIN32_APPDATA_DIR, "Config");
12083
12083
  } else if (process.env.XDG_CONFIG_HOME) {
12084
- return path6.join(process.env.XDG_CONFIG_HOME, "yarn");
12084
+ return path7.join(process.env.XDG_CONFIG_HOME, "yarn");
12085
12085
  } else {
12086
12086
  return FALLBACK_CONFIG_DIR;
12087
12087
  }
12088
12088
  }
12089
12089
  function getLocalAppDataDir() {
12090
- return process.env.LOCALAPPDATA ? path6.join(process.env.LOCALAPPDATA, "Yarn") : null;
12090
+ return process.env.LOCALAPPDATA ? path7.join(process.env.LOCALAPPDATA, "Yarn") : null;
12091
12091
  }
12092
12092
  },
12093
12093
  ,
@@ -13683,7 +13683,7 @@ ${indent}`);
13683
13683
  var Minimatch = minimatch.Minimatch;
13684
13684
  var Glob = __webpack_require__(75).Glob;
13685
13685
  var util = __webpack_require__(2);
13686
- var path6 = __webpack_require__(0);
13686
+ var path7 = __webpack_require__(0);
13687
13687
  var assert = __webpack_require__(22);
13688
13688
  var isAbsolute = __webpack_require__(76);
13689
13689
  var common = __webpack_require__(115);
@@ -13813,7 +13813,7 @@ ${indent}`);
13813
13813
  e = prefix + e;
13814
13814
  }
13815
13815
  if (e.charAt(0) === "/" && !this.nomount) {
13816
- e = path6.join(this.root, e);
13816
+ e = path7.join(this.root, e);
13817
13817
  }
13818
13818
  this._emitMatch(index, e);
13819
13819
  }
@@ -13962,9 +13962,9 @@ ${indent}`);
13962
13962
  if (prefix && isAbsolute(prefix) && !this.nomount) {
13963
13963
  var trail = /[\/\\]$/.test(prefix);
13964
13964
  if (prefix.charAt(0) === "/") {
13965
- prefix = path6.join(this.root, prefix);
13965
+ prefix = path7.join(this.root, prefix);
13966
13966
  } else {
13967
- prefix = path6.resolve(this.root, prefix);
13967
+ prefix = path7.resolve(this.root, prefix);
13968
13968
  if (trail)
13969
13969
  prefix += "/";
13970
13970
  }
@@ -14210,7 +14210,7 @@ ${indent}`);
14210
14210
  module2.exports = rimraf;
14211
14211
  rimraf.sync = rimrafSync;
14212
14212
  var assert = __webpack_require__(22);
14213
- var path6 = __webpack_require__(0);
14213
+ var path7 = __webpack_require__(0);
14214
14214
  var fs = __webpack_require__(3);
14215
14215
  var glob = __webpack_require__(75);
14216
14216
  var _0666 = parseInt("666", 8);
@@ -14395,7 +14395,7 @@ ${indent}`);
14395
14395
  return options.rmdir(p, cb);
14396
14396
  var errState;
14397
14397
  files.forEach(function(f) {
14398
- rimraf(path6.join(p, f), options, function(er2) {
14398
+ rimraf(path7.join(p, f), options, function(er2) {
14399
14399
  if (errState)
14400
14400
  return;
14401
14401
  if (er2)
@@ -14472,7 +14472,7 @@ ${indent}`);
14472
14472
  assert(p);
14473
14473
  assert(options);
14474
14474
  options.readdirSync(p).forEach(function(f) {
14475
- rimrafSync(path6.join(p, f), options);
14475
+ rimrafSync(path7.join(p, f), options);
14476
14476
  });
14477
14477
  var retries = isWindows ? 100 : 1;
14478
14478
  var i = 0;
@@ -14559,7 +14559,7 @@ ${indent}`);
14559
14559
 
14560
14560
  // src/cli/main.ts
14561
14561
  import { realpathSync as realpathSync2 } from "node:fs";
14562
- import path13 from "node:path";
14562
+ import path14 from "node:path";
14563
14563
  import { fileURLToPath as fileURLToPath2 } from "node:url";
14564
14564
 
14565
14565
  // src/shared/errors.ts
@@ -15175,7 +15175,7 @@ function parseDiffArgs(argv) {
15175
15175
  }
15176
15176
 
15177
15177
  // src/cli/version.ts
15178
- var OHRISK_VERSION = "0.127.1";
15178
+ var OHRISK_VERSION = "0.129.0";
15179
15179
 
15180
15180
  // src/diff/compare.ts
15181
15181
  function diffRiskFindings(input) {
@@ -15202,6 +15202,7 @@ import {
15202
15202
  closeSync as closeSync2,
15203
15203
  existsSync as existsSync2,
15204
15204
  openSync as openSync2,
15205
+ readdirSync as readdirSync2,
15205
15206
  readSync as readSync2,
15206
15207
  realpathSync,
15207
15208
  statSync as statSync3
@@ -15677,6 +15678,295 @@ function isZeroBlock(buffer) {
15677
15678
  return buffer.every((byte) => byte === 0);
15678
15679
  }
15679
15680
 
15681
+ // src/evidence/zip-package.ts
15682
+ import { inflateRawSync } from "node:zlib";
15683
+ var ZIP_EOCD_SIGNATURE = 101010256;
15684
+ var ZIP_CENTRAL_DIRECTORY_SIGNATURE = 33639248;
15685
+ var ZIP_LOCAL_FILE_SIGNATURE = 67324752;
15686
+ var ZIP64_SENTINEL = 4294967295;
15687
+ var ZIP_EOCD_MIN_BYTES = 22;
15688
+ var ZIP_MAX_COMMENT_BYTES = 65535;
15689
+ var PACKAGE_ZIP_MAX_ENTRIES = 50000;
15690
+ var PACKAGE_ZIP_ENTRY_MAX_BYTES = 2 * 1024 * 1024;
15691
+ function collectZipPackageEvidence(input) {
15692
+ const zip = Buffer.isBuffer(input.zip) ? input.zip : Buffer.from(input.zip);
15693
+ const entryMaxBytes = input.entryMaxBytes ?? PACKAGE_ZIP_ENTRY_MAX_BYTES;
15694
+ try {
15695
+ const entries = parseZipEntries({
15696
+ packageId: input.packageId,
15697
+ zip,
15698
+ maxEntries: input.maxEntries ?? PACKAGE_ZIP_MAX_ENTRIES
15699
+ });
15700
+ for (const packageJsonEntry of packageJsonEntries(entries)) {
15701
+ const packageJson = readPackageJsonEntry({
15702
+ packageId: input.packageId,
15703
+ zip,
15704
+ entry: packageJsonEntry,
15705
+ maxBytes: entryMaxBytes
15706
+ });
15707
+ if (!packageJson.ok) {
15708
+ return err(packageJson.error);
15709
+ }
15710
+ if (packageJson.value.packageJson.name !== input.packageName || packageJson.value.packageJson.version !== input.packageVersion) {
15711
+ continue;
15712
+ }
15713
+ const files = collectZipEvidenceFiles({
15714
+ packageId: input.packageId,
15715
+ zip,
15716
+ entries,
15717
+ packageRoot: packageJson.value.packageRoot,
15718
+ maxBytes: entryMaxBytes
15719
+ });
15720
+ if (!files.ok) {
15721
+ return err(files.error);
15722
+ }
15723
+ const warnings = files.value.length === 0 ? ["No LICENSE, LICENCE, UNLICENSE, COPYING, or NOTICE file found."] : [];
15724
+ return ok({
15725
+ packageId: input.packageId,
15726
+ ...readLicenseFields3(packageJson.value.packageJson),
15727
+ files: files.value,
15728
+ source: "local",
15729
+ warnings
15730
+ });
15731
+ }
15732
+ return ok(undefined);
15733
+ } catch (cause) {
15734
+ return err(createError({
15735
+ code: "PACKAGE_EVIDENCE_READ_FAILED",
15736
+ category: "unsupported_input",
15737
+ message: "Failed to parse package zip cache evidence.",
15738
+ details: {
15739
+ packageId: input.packageId,
15740
+ cause: cause instanceof Error ? cause.message : String(cause)
15741
+ }
15742
+ }));
15743
+ }
15744
+ }
15745
+ function parseZipEntries(input) {
15746
+ const endOfCentralDirectoryOffset = findEndOfCentralDirectory(input.zip);
15747
+ if (endOfCentralDirectoryOffset === undefined) {
15748
+ throw new Error("ZIP end of central directory record was not found.");
15749
+ }
15750
+ const diskNumber = input.zip.readUInt16LE(endOfCentralDirectoryOffset + 4);
15751
+ const centralDirectoryDisk = input.zip.readUInt16LE(endOfCentralDirectoryOffset + 6);
15752
+ const entriesOnDisk = input.zip.readUInt16LE(endOfCentralDirectoryOffset + 8);
15753
+ const totalEntries = input.zip.readUInt16LE(endOfCentralDirectoryOffset + 10);
15754
+ const centralDirectorySize = input.zip.readUInt32LE(endOfCentralDirectoryOffset + 12);
15755
+ const centralDirectoryOffset = input.zip.readUInt32LE(endOfCentralDirectoryOffset + 16);
15756
+ if (diskNumber !== 0 || centralDirectoryDisk !== 0 || entriesOnDisk !== totalEntries) {
15757
+ throw new Error("Multi-disk ZIP archives are not supported.");
15758
+ }
15759
+ if (totalEntries === ZIP64_SENTINEL || centralDirectorySize === ZIP64_SENTINEL || centralDirectoryOffset === ZIP64_SENTINEL) {
15760
+ throw new Error("ZIP64 package cache archives are not supported.");
15761
+ }
15762
+ if (totalEntries > input.maxEntries) {
15763
+ throw new Error(`Package ZIP exceeded the maximum entry count (${input.maxEntries}).`);
15764
+ }
15765
+ const centralDirectoryEnd = centralDirectoryOffset + centralDirectorySize;
15766
+ if (centralDirectoryOffset < 0 || centralDirectorySize < 0 || centralDirectoryEnd > input.zip.length) {
15767
+ throw new Error("ZIP central directory extends beyond archive data.");
15768
+ }
15769
+ const entries = [];
15770
+ let offset = centralDirectoryOffset;
15771
+ while (offset < centralDirectoryEnd) {
15772
+ if (offset + 46 > input.zip.length) {
15773
+ throw new Error("ZIP central directory entry is truncated.");
15774
+ }
15775
+ const signature = input.zip.readUInt32LE(offset);
15776
+ if (signature !== ZIP_CENTRAL_DIRECTORY_SIGNATURE) {
15777
+ throw new Error("ZIP central directory entry has an invalid signature.");
15778
+ }
15779
+ const flags = input.zip.readUInt16LE(offset + 8);
15780
+ const compressionMethod = input.zip.readUInt16LE(offset + 10);
15781
+ const compressedSize = input.zip.readUInt32LE(offset + 20);
15782
+ const uncompressedSize = input.zip.readUInt32LE(offset + 24);
15783
+ const fileNameLength = input.zip.readUInt16LE(offset + 28);
15784
+ const extraLength = input.zip.readUInt16LE(offset + 30);
15785
+ const commentLength = input.zip.readUInt16LE(offset + 32);
15786
+ const localHeaderOffset = input.zip.readUInt32LE(offset + 42);
15787
+ const entryEnd = offset + 46 + fileNameLength + extraLength + commentLength;
15788
+ if (entryEnd > centralDirectoryEnd || entryEnd > input.zip.length) {
15789
+ throw new Error("ZIP central directory entry metadata is truncated.");
15790
+ }
15791
+ if ((flags & 1) !== 0) {
15792
+ throw new Error("Encrypted ZIP entries are not supported.");
15793
+ }
15794
+ if (compressedSize === ZIP64_SENTINEL || uncompressedSize === ZIP64_SENTINEL || localHeaderOffset === ZIP64_SENTINEL) {
15795
+ throw new Error("ZIP64 package cache entries are not supported.");
15796
+ }
15797
+ const rawPath = input.zip.subarray(offset + 46, offset + 46 + fileNameLength).toString("utf8");
15798
+ const normalizedPath = normalizeZipPath(rawPath);
15799
+ if (normalizedPath && !normalizedPath.endsWith("/")) {
15800
+ entries.push({
15801
+ path: normalizedPath,
15802
+ compressionMethod,
15803
+ compressedSize,
15804
+ uncompressedSize,
15805
+ localHeaderOffset
15806
+ });
15807
+ }
15808
+ offset = entryEnd;
15809
+ }
15810
+ return entries.sort((left, right) => left.path.localeCompare(right.path));
15811
+ }
15812
+ function findEndOfCentralDirectory(zip) {
15813
+ if (zip.length < ZIP_EOCD_MIN_BYTES) {
15814
+ return;
15815
+ }
15816
+ const minOffset = Math.max(0, zip.length - ZIP_EOCD_MIN_BYTES - ZIP_MAX_COMMENT_BYTES);
15817
+ for (let offset = zip.length - ZIP_EOCD_MIN_BYTES;offset >= minOffset; offset -= 1) {
15818
+ if (zip.readUInt32LE(offset) !== ZIP_EOCD_SIGNATURE) {
15819
+ continue;
15820
+ }
15821
+ const commentLength = zip.readUInt16LE(offset + 20);
15822
+ if (offset + ZIP_EOCD_MIN_BYTES + commentLength === zip.length) {
15823
+ return offset;
15824
+ }
15825
+ }
15826
+ return;
15827
+ }
15828
+ function packageJsonEntries(entries) {
15829
+ return entries.filter((entry) => entry.path === "package.json" || entry.path.endsWith("/package.json"));
15830
+ }
15831
+ function readPackageJsonEntry(input) {
15832
+ if (input.entry.uncompressedSize > input.maxBytes) {
15833
+ return err(createError({
15834
+ code: "PACKAGE_EVIDENCE_READ_FAILED",
15835
+ category: "unsupported_input",
15836
+ message: "Package zip cache package.json exceeded the maximum supported size.",
15837
+ details: {
15838
+ packageId: input.packageId,
15839
+ packageJsonPath: input.entry.path,
15840
+ maxBytes: input.maxBytes,
15841
+ observedBytes: input.entry.uncompressedSize
15842
+ }
15843
+ }));
15844
+ }
15845
+ const packageJsonData = readZipEntryData({
15846
+ zip: input.zip,
15847
+ entry: input.entry,
15848
+ maxBytes: input.maxBytes
15849
+ });
15850
+ try {
15851
+ const packageJson = JSON.parse(packageJsonData.toString("utf8"));
15852
+ if (!isObjectRecord3(packageJson)) {
15853
+ throw new Error("Expected package.json to contain an object.");
15854
+ }
15855
+ return ok({
15856
+ packageJson,
15857
+ packageRoot: packageRootForPackageJsonPath(input.entry.path)
15858
+ });
15859
+ } catch (cause) {
15860
+ return err(createError({
15861
+ code: "PACKAGE_JSON_PARSE_FAILED",
15862
+ category: "unsupported_input",
15863
+ message: "Failed to parse package.json from package zip cache.",
15864
+ details: {
15865
+ packageId: input.packageId,
15866
+ packageJsonPath: input.entry.path,
15867
+ cause: cause instanceof Error ? cause.message : String(cause)
15868
+ }
15869
+ }));
15870
+ }
15871
+ }
15872
+ function collectZipEvidenceFiles(input) {
15873
+ const files = [];
15874
+ for (const entry of input.entries) {
15875
+ const normalizedPath = normalizePackagePath2(entry.path, input.packageRoot);
15876
+ if (!isRootPackageFile2(normalizedPath)) {
15877
+ continue;
15878
+ }
15879
+ const kind = classifyEvidenceFile(normalizedPath);
15880
+ if (!kind) {
15881
+ continue;
15882
+ }
15883
+ if (entry.uncompressedSize > input.maxBytes) {
15884
+ continue;
15885
+ }
15886
+ files.push({
15887
+ path: normalizedPath,
15888
+ kind,
15889
+ text: readZipEntryData({
15890
+ zip: input.zip,
15891
+ entry,
15892
+ maxBytes: input.maxBytes
15893
+ }).toString("utf8")
15894
+ });
15895
+ }
15896
+ return ok(files.sort((left, right) => left.path.localeCompare(right.path)));
15897
+ }
15898
+ function readZipEntryData(input) {
15899
+ if (input.entry.uncompressedSize > input.maxBytes) {
15900
+ throw new Error(`ZIP entry ${input.entry.path} exceeded the maximum supported size.`);
15901
+ }
15902
+ if (input.entry.localHeaderOffset + 30 > input.zip.length) {
15903
+ throw new Error(`ZIP local file header for ${input.entry.path} is truncated.`);
15904
+ }
15905
+ const localSignature = input.zip.readUInt32LE(input.entry.localHeaderOffset);
15906
+ if (localSignature !== ZIP_LOCAL_FILE_SIGNATURE) {
15907
+ throw new Error(`ZIP local file header for ${input.entry.path} has an invalid signature.`);
15908
+ }
15909
+ const fileNameLength = input.zip.readUInt16LE(input.entry.localHeaderOffset + 26);
15910
+ const extraLength = input.zip.readUInt16LE(input.entry.localHeaderOffset + 28);
15911
+ const dataStart = input.entry.localHeaderOffset + 30 + fileNameLength + extraLength;
15912
+ const dataEnd = dataStart + input.entry.compressedSize;
15913
+ if (dataEnd > input.zip.length || dataEnd < dataStart) {
15914
+ throw new Error(`ZIP entry ${input.entry.path} extends beyond archive data.`);
15915
+ }
15916
+ const compressedData = input.zip.subarray(dataStart, dataEnd);
15917
+ if (input.entry.compressionMethod === 0) {
15918
+ if (compressedData.length !== input.entry.uncompressedSize) {
15919
+ throw new Error(`Stored ZIP entry ${input.entry.path} size did not match metadata.`);
15920
+ }
15921
+ return compressedData;
15922
+ }
15923
+ if (input.entry.compressionMethod === 8) {
15924
+ const inflated = inflateRawSync(compressedData, {
15925
+ maxOutputLength: input.entry.uncompressedSize
15926
+ });
15927
+ if (inflated.length !== input.entry.uncompressedSize) {
15928
+ throw new Error(`Deflated ZIP entry ${input.entry.path} size did not match metadata.`);
15929
+ }
15930
+ return inflated;
15931
+ }
15932
+ throw new Error(`ZIP entry ${input.entry.path} uses unsupported compression method ${input.entry.compressionMethod}.`);
15933
+ }
15934
+ function packageRootForPackageJsonPath(packageJsonPath) {
15935
+ return packageJsonPath === "package.json" ? "" : packageJsonPath.slice(0, -"/package.json".length);
15936
+ }
15937
+ function normalizePackagePath2(filePath, packageRoot) {
15938
+ if (packageRoot === "") {
15939
+ return filePath;
15940
+ }
15941
+ return filePath.startsWith(`${packageRoot}/`) ? filePath.slice(packageRoot.length + 1) : "";
15942
+ }
15943
+ function isRootPackageFile2(normalizedPath) {
15944
+ return normalizedPath.length > 0 && !normalizedPath.includes("/");
15945
+ }
15946
+ function normalizeZipPath(filePath) {
15947
+ if (filePath === "" || filePath.includes("\x00") || filePath.includes("\\") || filePath.startsWith("/") || /^[A-Za-z]:/.test(filePath)) {
15948
+ return;
15949
+ }
15950
+ const segments = filePath.split("/");
15951
+ if (segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
15952
+ return;
15953
+ }
15954
+ return segments.join("/");
15955
+ }
15956
+ function readLicenseFields3(packageJson) {
15957
+ const license = packageJson.license;
15958
+ const licenses = packageJson.licenses;
15959
+ const legacyLicenseObject = isObjectRecord3(license) ? license : undefined;
15960
+ return {
15961
+ ...typeof license === "string" ? { packageJsonLicense: license } : {},
15962
+ ...legacyLicenseObject !== undefined ? { packageJsonLicenses: legacyLicenseObject } : {},
15963
+ ...licenses !== undefined ? { packageJsonLicenses: licenses } : {}
15964
+ };
15965
+ }
15966
+ function isObjectRecord3(value) {
15967
+ return typeof value === "object" && value !== null && !Array.isArray(value);
15968
+ }
15969
+
15680
15970
  // src/evidence/collect.ts
15681
15971
  var ARTIFACT_FETCH_TIMEOUT_MS = 30000;
15682
15972
  var REGISTRY_METADATA_MAX_BYTES = 10 * 1024 * 1024;
@@ -15745,6 +16035,17 @@ async function collectNodeEvidence(input) {
15745
16035
  packageDir: nodeModulesPath
15746
16036
  });
15747
16037
  }
16038
+ const yarnCacheEvidence = collectYarnCachePackageEvidence({
16039
+ node: input.node,
16040
+ projectRoot: input.projectRoot,
16041
+ zipMaxBytes: input.tarballMaxBytes
16042
+ });
16043
+ if (!yarnCacheEvidence.ok) {
16044
+ return err(yarnCacheEvidence.error);
16045
+ }
16046
+ if (yarnCacheEvidence.value) {
16047
+ return ok(yarnCacheEvidence.value);
16048
+ }
15748
16049
  if (!input.node.resolved) {
15749
16050
  return collectRegistryTarballEvidence({
15750
16051
  node: input.node,
@@ -16183,6 +16484,81 @@ function installedPackageMatchesNode(input) {
16183
16484
  return false;
16184
16485
  }
16185
16486
  }
16487
+ function collectYarnCachePackageEvidence(input) {
16488
+ const cacheDir = path2.join(input.projectRoot, ".yarn", "cache");
16489
+ if (!existsSync2(cacheDir) || !isReadableDirectory(cacheDir)) {
16490
+ return ok(undefined);
16491
+ }
16492
+ const filenamePrefix = yarnCacheFilenamePrefix(input.node);
16493
+ if (!filenamePrefix) {
16494
+ return ok(undefined);
16495
+ }
16496
+ let entries;
16497
+ try {
16498
+ entries = readdirSync2(cacheDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.startsWith(filenamePrefix) && entry.name.endsWith(".zip")).sort((left, right) => left.name.localeCompare(right.name));
16499
+ } catch (cause) {
16500
+ return err(createError({
16501
+ code: "PACKAGE_EVIDENCE_READ_FAILED",
16502
+ category: "filesystem",
16503
+ message: "Failed to read Yarn package cache directory.",
16504
+ details: {
16505
+ packageId: input.node.id,
16506
+ cacheDir,
16507
+ cause: safeUrlForErrorDetails(cause instanceof Error ? cause.message : String(cause))
16508
+ }
16509
+ }));
16510
+ }
16511
+ for (const entry of entries) {
16512
+ const cachePath = path2.join(cacheDir, entry.name);
16513
+ const stats = readLocalArtifactStats({
16514
+ filePath: cachePath,
16515
+ packageId: input.node.id,
16516
+ resolved: undefined
16517
+ });
16518
+ if (!stats.ok) {
16519
+ return err(stats.error);
16520
+ }
16521
+ if (stats.value.size > input.zipMaxBytes) {
16522
+ return err(localArtifactTooLargeError({
16523
+ packageId: input.node.id,
16524
+ resolved: undefined,
16525
+ artifactPath: cachePath,
16526
+ maxBytes: input.zipMaxBytes,
16527
+ observedBytes: stats.value.size
16528
+ }));
16529
+ }
16530
+ const zip = readLocalArtifactFileWithLimit({
16531
+ filePath: cachePath,
16532
+ packageId: input.node.id,
16533
+ resolved: undefined,
16534
+ maxBytes: input.zipMaxBytes
16535
+ });
16536
+ if (!zip.ok) {
16537
+ return err(zip.error);
16538
+ }
16539
+ const evidence = collectZipPackageEvidence({
16540
+ packageId: input.node.id,
16541
+ packageName: input.node.name,
16542
+ packageVersion: input.node.version,
16543
+ zip: zip.value
16544
+ });
16545
+ if (!evidence.ok) {
16546
+ return err(evidence.error);
16547
+ }
16548
+ if (evidence.value) {
16549
+ return ok(evidence.value);
16550
+ }
16551
+ }
16552
+ return ok(undefined);
16553
+ }
16554
+ function yarnCacheFilenamePrefix(node) {
16555
+ const slug = yarnCachePackageSlug(node.name);
16556
+ return slug ? `${slug}-npm-${node.version}-` : undefined;
16557
+ }
16558
+ function yarnCachePackageSlug(packageName) {
16559
+ const segments = nodeModulesPackageSegments(packageName);
16560
+ return segments ? segments.join("-") : undefined;
16561
+ }
16186
16562
  async function collectRemoteTarballEvidence(input) {
16187
16563
  const urlError = input.urlError ?? {
16188
16564
  code: "TARBALL_FETCH_FAILED",
@@ -17219,7 +17595,7 @@ function readFailedError(input) {
17219
17595
  });
17220
17596
  }
17221
17597
  function readProcessErrorText(cause) {
17222
- if (isObjectRecord3(cause)) {
17598
+ if (isObjectRecord4(cause)) {
17223
17599
  const stderr = cause.stderr;
17224
17600
  if (typeof stderr === "string" && stderr.trim() !== "") {
17225
17601
  return stderr.trim();
@@ -17248,7 +17624,7 @@ function toGitObjectPath(input) {
17248
17624
  function isOutsideRelativePath(relativePath) {
17249
17625
  return relativePath === ".." || relativePath.startsWith(`..${path3.sep}`) || path3.isAbsolute(relativePath);
17250
17626
  }
17251
- function isObjectRecord3(value) {
17627
+ function isObjectRecord4(value) {
17252
17628
  return typeof value === "object" && value !== null;
17253
17629
  }
17254
17630
 
@@ -17266,6 +17642,17 @@ function resolveNpmDependencyReference(requestedName, range) {
17266
17642
  aliased: alias.name !== requestedName
17267
17643
  };
17268
17644
  }
17645
+ if (range.startsWith("npm:")) {
17646
+ const bareRange = range.slice("npm:".length);
17647
+ if (bareRange !== "") {
17648
+ return {
17649
+ requestedName,
17650
+ lookupName: requestedName,
17651
+ lookupRange: bareRange,
17652
+ aliased: false
17653
+ };
17654
+ }
17655
+ }
17269
17656
  return {
17270
17657
  requestedName,
17271
17658
  lookupName: requestedName,
@@ -17383,7 +17770,7 @@ function parseDenoLockText(input, lockfilePath = "deno.lock") {
17383
17770
  function parseLockfileJson(input, lockfilePath) {
17384
17771
  try {
17385
17772
  const parsed = JSON.parse(input);
17386
- if (!isObjectRecord4(parsed)) {
17773
+ if (!isObjectRecord5(parsed)) {
17387
17774
  return denoParseFailed(lockfilePath, "deno.lock root must be a JSON object.");
17388
17775
  }
17389
17776
  return ok(parsed);
@@ -17411,18 +17798,18 @@ function denoParseFailed(lockfilePath, cause) {
17411
17798
  }));
17412
17799
  }
17413
17800
  function readNpmPackageMap(lockfile) {
17414
- if (isObjectRecord4(lockfile.npm)) {
17801
+ if (isObjectRecord5(lockfile.npm)) {
17415
17802
  return lockfile.npm;
17416
17803
  }
17417
- const packages = isObjectRecord4(lockfile.packages) ? lockfile.packages : undefined;
17418
- return isObjectRecord4(packages?.npm) ? packages.npm : {};
17804
+ const packages = isObjectRecord5(lockfile.packages) ? lockfile.packages : undefined;
17805
+ return isObjectRecord5(packages?.npm) ? packages.npm : {};
17419
17806
  }
17420
17807
  function readSpecifierMap(lockfile) {
17421
- if (isObjectRecord4(lockfile.specifiers)) {
17808
+ if (isObjectRecord5(lockfile.specifiers)) {
17422
17809
  return readStringMap(lockfile.specifiers);
17423
17810
  }
17424
- const packages = isObjectRecord4(lockfile.packages) ? lockfile.packages : undefined;
17425
- return isObjectRecord4(packages?.specifiers) ? readStringMap(packages.specifiers) : {};
17811
+ const packages = isObjectRecord5(lockfile.packages) ? lockfile.packages : undefined;
17812
+ return isObjectRecord5(packages?.specifiers) ? readStringMap(packages.specifiers) : {};
17426
17813
  }
17427
17814
  function collectRootDependencies(lockfile, specifiers) {
17428
17815
  const workspaceDependencies = readWorkspaceDependencies(lockfile).filter((specifier) => specifier.startsWith("npm:"));
@@ -17442,7 +17829,7 @@ function collectRootDependencies(lockfile, specifiers) {
17442
17829
  return edges;
17443
17830
  }
17444
17831
  function readWorkspaceDependencies(lockfile) {
17445
- const workspace = isObjectRecord4(lockfile.workspace) ? lockfile.workspace : isObjectRecord4(lockfile.packages) && isObjectRecord4(lockfile.packages.workspace) ? lockfile.packages.workspace : undefined;
17832
+ const workspace = isObjectRecord5(lockfile.workspace) ? lockfile.workspace : isObjectRecord5(lockfile.packages) && isObjectRecord5(lockfile.packages.workspace) ? lockfile.packages.workspace : undefined;
17446
17833
  if (!workspace || !Array.isArray(workspace.dependencies)) {
17447
17834
  return [];
17448
17835
  }
@@ -17452,7 +17839,7 @@ function parseNpmRecords(packages) {
17452
17839
  const records = [];
17453
17840
  for (const [key, rawPackage] of Object.entries(packages)) {
17454
17841
  const packageKey = parseDenoNpmPackageKey(key);
17455
- if (!packageKey || !isObjectRecord4(rawPackage)) {
17842
+ if (!packageKey || !isObjectRecord5(rawPackage)) {
17456
17843
  continue;
17457
17844
  }
17458
17845
  const pkg = rawPackage;
@@ -17499,7 +17886,7 @@ function readDependencyEdges(value, type) {
17499
17886
  return parsed ? [{ name: parsed.name, range: parsed.version, type }] : [];
17500
17887
  });
17501
17888
  }
17502
- if (!isObjectRecord4(value)) {
17889
+ if (!isObjectRecord5(value)) {
17503
17890
  return [];
17504
17891
  }
17505
17892
  const edges = [];
@@ -17752,7 +18139,7 @@ function rootNameForLockfile(lockfilePath) {
17752
18139
  function isGitRefSyntheticPath(lockfilePath) {
17753
18140
  return lockfilePath.includes(":") && !/^[A-Za-z]:[\\/]/.test(lockfilePath);
17754
18141
  }
17755
- function isObjectRecord4(value) {
18142
+ function isObjectRecord5(value) {
17756
18143
  return typeof value === "object" && value !== null && !Array.isArray(value);
17757
18144
  }
17758
18145
 
@@ -17875,7 +18262,7 @@ function readPackageTupleFields(input) {
17875
18262
  const resolved2 = registryOrMetadata !== "" ? registryOrMetadata : undefined;
17876
18263
  const parsedIntegrity2 = typeof integrity === "string" && integrity !== "" ? integrity : undefined;
17877
18264
  return {
17878
- metadata: isObjectRecord5(metadataOrIntegrity) ? metadataOrIntegrity : {},
18265
+ metadata: isObjectRecord6(metadataOrIntegrity) ? metadataOrIntegrity : {},
17879
18266
  ...resolved2 ? { resolved: resolved2 } : {},
17880
18267
  ...parsedIntegrity2 ? { integrity: parsedIntegrity2 } : {}
17881
18268
  };
@@ -17883,7 +18270,7 @@ function readPackageTupleFields(input) {
17883
18270
  const resolved = isLocalArtifactReference(input.identity.version) ? input.identity.version : undefined;
17884
18271
  const parsedIntegrity = typeof metadataOrIntegrity === "string" && metadataOrIntegrity !== "" ? metadataOrIntegrity : undefined;
17885
18272
  return {
17886
- metadata: isObjectRecord5(registryOrMetadata) ? registryOrMetadata : {},
18273
+ metadata: isObjectRecord6(registryOrMetadata) ? registryOrMetadata : {},
17887
18274
  ...resolved ? { resolved } : {},
17888
18275
  ...parsedIntegrity ? { integrity: parsedIntegrity } : {}
17889
18276
  };
@@ -17912,10 +18299,10 @@ function readWorkspaceEntries(workspaces) {
17912
18299
  if (!workspaces) {
17913
18300
  return [];
17914
18301
  }
17915
- const rootWorkspace = isObjectRecord5(workspaces[""]) ? workspaces[""] : undefined;
18302
+ const rootWorkspace = isObjectRecord6(workspaces[""]) ? workspaces[""] : undefined;
17916
18303
  const rootName = readWorkspaceName(rootWorkspace);
17917
18304
  return Object.entries(workspaces).flatMap(([key, workspace]) => {
17918
- if (!isObjectRecord5(workspace)) {
18305
+ if (!isObjectRecord6(workspace)) {
17919
18306
  return [];
17920
18307
  }
17921
18308
  return [{
@@ -17971,7 +18358,7 @@ function dependencyEntries(value, type) {
17971
18358
  }));
17972
18359
  }
17973
18360
  function readDependencyMap(value) {
17974
- if (!isObjectRecord5(value)) {
18361
+ if (!isObjectRecord6(value)) {
17975
18362
  return {};
17976
18363
  }
17977
18364
  const dependencies = {};
@@ -18069,7 +18456,7 @@ function dependencyTypeRank2(type) {
18069
18456
  return 0;
18070
18457
  }
18071
18458
  }
18072
- function isObjectRecord5(value) {
18459
+ function isObjectRecord6(value) {
18073
18460
  return typeof value === "object" && value !== null && !Array.isArray(value);
18074
18461
  }
18075
18462
 
@@ -18100,14 +18487,14 @@ function parsePackageLockText(input, lockfilePath = "package-lock.json") {
18100
18487
  return parsed;
18101
18488
  }
18102
18489
  const lockfile = parsed.value;
18103
- if (!isObjectRecord6(lockfile.packages) && isObjectRecord6(lockfile.dependencies)) {
18490
+ if (!isObjectRecord7(lockfile.packages) && isObjectRecord7(lockfile.dependencies)) {
18104
18491
  return parsePackageLockV1({
18105
18492
  lockfile,
18106
18493
  lockfilePath,
18107
18494
  dependencies: lockfile.dependencies
18108
18495
  });
18109
18496
  }
18110
- if (!isObjectRecord6(lockfile.packages)) {
18497
+ if (!isObjectRecord7(lockfile.packages)) {
18111
18498
  return err(createError({
18112
18499
  code: "PACKAGE_LOCK_PARSE_FAILED",
18113
18500
  category: "unsupported_input",
@@ -18457,13 +18844,13 @@ function dependencyTypeRank3(type) {
18457
18844
  }
18458
18845
  }
18459
18846
  function readPackage(value) {
18460
- return isObjectRecord6(value) ? value : undefined;
18847
+ return isObjectRecord7(value) ? value : undefined;
18461
18848
  }
18462
18849
  function readV1Dependency(value) {
18463
- return isObjectRecord6(value) ? value : undefined;
18850
+ return isObjectRecord7(value) ? value : undefined;
18464
18851
  }
18465
18852
  function readV1DependencyMap(value) {
18466
- if (!isObjectRecord6(value)) {
18853
+ if (!isObjectRecord7(value)) {
18467
18854
  return {};
18468
18855
  }
18469
18856
  const dependencies = {};
@@ -18485,7 +18872,7 @@ function dependencyTypeForV1Dependency(dependency) {
18485
18872
  return "production";
18486
18873
  }
18487
18874
  function readDependencyMap2(value) {
18488
- if (!isObjectRecord6(value)) {
18875
+ if (!isObjectRecord7(value)) {
18489
18876
  return {};
18490
18877
  }
18491
18878
  const dependencies = {};
@@ -18496,10 +18883,14 @@ function readDependencyMap2(value) {
18496
18883
  }
18497
18884
  return dependencies;
18498
18885
  }
18499
- function isObjectRecord6(value) {
18886
+ function isObjectRecord7(value) {
18500
18887
  return typeof value === "object" && value !== null && !Array.isArray(value);
18501
18888
  }
18502
18889
 
18890
+ // src/graph/npm-pnpm-lock.ts
18891
+ import { existsSync as existsSync3 } from "node:fs";
18892
+ import path6 from "node:path";
18893
+
18503
18894
  // node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js
18504
18895
  var composer = require_composer();
18505
18896
  var Document = require_Document();
@@ -18563,13 +18954,30 @@ function parsePnpmLockfile(lockfilePath, options = {}) {
18563
18954
  }
18564
18955
  }));
18565
18956
  }
18566
- return parsePnpmLockText(lockfileText.value, lockfilePath);
18957
+ const workspaceCatalogs = readPnpmWorkspaceCatalogs({
18958
+ lockfilePath,
18959
+ maxBytes: options.workspaceMaxBytes ?? LOCKFILE_MAX_BYTES
18960
+ });
18961
+ if (!workspaceCatalogs.ok) {
18962
+ return workspaceCatalogs;
18963
+ }
18964
+ return parsePnpmLockText(lockfileText.value, lockfilePath, {
18965
+ catalogs: workspaceCatalogs.value
18966
+ });
18567
18967
  }
18568
- function parsePnpmLockText(input, lockfilePath = "pnpm-lock.yaml") {
18968
+ function parsePnpmLockText(input, lockfilePath = "pnpm-lock.yaml", options = {}) {
18569
18969
  const parsed = parseLockfileYaml(input, lockfilePath);
18570
18970
  if (!parsed.ok) {
18571
18971
  return parsed;
18572
18972
  }
18973
+ const catalogs = resolvePnpmCatalogs({
18974
+ workspaceText: options.workspaceText,
18975
+ workspacePath: options.workspacePath,
18976
+ catalogs: options.catalogs
18977
+ });
18978
+ if (!catalogs.ok) {
18979
+ return catalogs;
18980
+ }
18573
18981
  const lockfile = parsed.value;
18574
18982
  const importers = readRecord(lockfile.importers);
18575
18983
  if (!importers) {
@@ -18583,14 +18991,18 @@ function parsePnpmLockText(input, lockfilePath = "pnpm-lock.yaml") {
18583
18991
  }
18584
18992
  }));
18585
18993
  }
18586
- const importerEntries = readImporterEntries(importers);
18994
+ const importerEntries = readImporterEntries(importers, catalogs.value);
18587
18995
  const packages = readRecord(lockfile.packages) ?? {};
18588
18996
  const snapshots = readRecord(lockfile.snapshots) ?? {};
18589
- const records = parsePackageRecords3({ packages, snapshots });
18997
+ const records = parsePackageRecords3({
18998
+ packages,
18999
+ snapshots,
19000
+ catalogs: catalogs.value
19001
+ });
18590
19002
  const packageIndex = indexPackagesByName2(records);
18591
19003
  const nodeMap = new Map;
18592
19004
  for (const importerEntry of importerEntries) {
18593
- for (const rootDependency of collectRootDependencies4(importerEntry.importer)) {
19005
+ for (const rootDependency of collectRootDependencies4(importerEntry.importer, catalogs.value)) {
18594
19006
  const record = resolvePackageRecord3({
18595
19007
  packageIndex,
18596
19008
  name: rootDependency.name,
@@ -18619,7 +19031,7 @@ function parsePnpmLockText(input, lockfilePath = "pnpm-lock.yaml") {
18619
19031
  function parseLockfileYaml(input, lockfilePath) {
18620
19032
  try {
18621
19033
  const parsed = $parse(input);
18622
- if (!isObjectRecord7(parsed)) {
19034
+ if (!isObjectRecord8(parsed)) {
18623
19035
  throw new Error("Expected a YAML mapping at the document root.");
18624
19036
  }
18625
19037
  return ok(parsed);
@@ -18635,14 +19047,100 @@ function parseLockfileYaml(input, lockfilePath) {
18635
19047
  }));
18636
19048
  }
18637
19049
  }
18638
- function readImporterEntries(importers) {
19050
+ function readPnpmWorkspaceCatalogs(input) {
19051
+ const workspacePath = path6.join(path6.dirname(input.lockfilePath), "pnpm-workspace.yaml");
19052
+ if (!existsSync3(workspacePath)) {
19053
+ return ok(emptyPnpmCatalogs());
19054
+ }
19055
+ const workspaceText = readInputTextFile({
19056
+ filePath: workspacePath,
19057
+ maxBytes: input.maxBytes
19058
+ });
19059
+ if (!workspaceText.ok) {
19060
+ return err(createError({
19061
+ code: "PNPM_WORKSPACE_READ_FAILED",
19062
+ category: inputFileReadErrorCategory(workspaceText.error),
19063
+ message: workspaceText.error.kind === "too_large" ? "pnpm-workspace.yaml exceeded the maximum supported size." : "Failed to read pnpm-workspace.yaml.",
19064
+ details: {
19065
+ workspacePath,
19066
+ ...inputFileReadErrorDetails(workspaceText.error)
19067
+ }
19068
+ }));
19069
+ }
19070
+ return parsePnpmWorkspaceCatalogsText(workspaceText.value, workspacePath);
19071
+ }
19072
+ function resolvePnpmCatalogs(input) {
19073
+ if (input.catalogs) {
19074
+ return ok(input.catalogs);
19075
+ }
19076
+ if (input.workspaceText !== undefined) {
19077
+ return parsePnpmWorkspaceCatalogsText(input.workspaceText, input.workspacePath ?? "pnpm-workspace.yaml");
19078
+ }
19079
+ return ok(emptyPnpmCatalogs());
19080
+ }
19081
+ function parsePnpmWorkspaceCatalogsText(input, workspacePath) {
19082
+ try {
19083
+ const parsed = $parse(input);
19084
+ if (parsed === null || parsed === undefined) {
19085
+ return ok(emptyPnpmCatalogs());
19086
+ }
19087
+ if (!isObjectRecord8(parsed)) {
19088
+ throw new Error("Expected a YAML mapping at the document root.");
19089
+ }
19090
+ const workspace = parsed;
19091
+ const namedCatalogs = new Map;
19092
+ const catalogs = readRecord(workspace.catalogs);
19093
+ if (catalogs) {
19094
+ for (const [name, value] of Object.entries(catalogs)) {
19095
+ const catalog = readCatalogMap(value);
19096
+ if (catalog) {
19097
+ namedCatalogs.set(name, catalog);
19098
+ }
19099
+ }
19100
+ }
19101
+ return ok({
19102
+ defaultCatalog: readCatalogMap(workspace.catalog) ?? {},
19103
+ namedCatalogs
19104
+ });
19105
+ } catch (cause) {
19106
+ return err(createError({
19107
+ code: "PNPM_WORKSPACE_PARSE_FAILED",
19108
+ category: "unsupported_input",
19109
+ message: "Failed to parse pnpm-workspace.yaml catalog definitions.",
19110
+ details: {
19111
+ workspacePath,
19112
+ cause: cause instanceof Error ? cause.message : String(cause)
19113
+ }
19114
+ }));
19115
+ }
19116
+ }
19117
+ function emptyPnpmCatalogs() {
19118
+ return {
19119
+ defaultCatalog: {},
19120
+ namedCatalogs: new Map
19121
+ };
19122
+ }
19123
+ function readCatalogMap(value) {
19124
+ const record = readRecord(value);
19125
+ if (!record) {
19126
+ return;
19127
+ }
19128
+ const catalog = {};
19129
+ for (const [name, range] of Object.entries(record)) {
19130
+ if (typeof range === "string" && range !== "") {
19131
+ catalog[name] = range;
19132
+ }
19133
+ }
19134
+ return catalog;
19135
+ }
19136
+ function readImporterEntries(importers, catalogs) {
18639
19137
  return Object.entries(importers).flatMap(([key, value]) => {
18640
19138
  const importer = readRecord(value);
18641
19139
  if (!importer) {
18642
19140
  return [];
18643
19141
  }
18644
19142
  return [{
18645
- importer,
19143
+ importer: resolveImporterCatalogReferences(importer, catalogs),
18646
19144
  pathSegment: importerPathSegment(key)
18647
19145
  }];
18648
19146
  });
@@ -18670,7 +19168,7 @@ function parsePackageRecords3(input) {
18670
19168
  id: `${identity2.name}@${identity2.version}`,
18671
19169
  ...resolved ? { resolved } : {},
18672
19170
  ...integrity ? { integrity } : {},
18673
- dependencies: collectDependencyEdges3(packageEntry, snapshotEntry)
19171
+ dependencies: collectDependencyEdges3(input.catalogs, packageEntry, snapshotEntry)
18674
19172
  });
18675
19173
  }
18676
19174
  return records;
@@ -18714,24 +19212,92 @@ function readResolvedArtifact(resolution) {
18714
19212
  }
18715
19213
  return;
18716
19214
  }
18717
- function collectRootDependencies4(importer) {
19215
+ function resolveImporterCatalogReferences(importer, catalogs) {
19216
+ return {
19217
+ ...importer,
19218
+ dependencies: resolveDependencyCatalogReferences(importer.dependencies, catalogs),
19219
+ devDependencies: resolveDependencyCatalogReferences(importer.devDependencies, catalogs),
19220
+ optionalDependencies: resolveDependencyCatalogReferences(importer.optionalDependencies, catalogs),
19221
+ peerDependencies: resolveDependencyCatalogReferences(importer.peerDependencies, catalogs)
19222
+ };
19223
+ }
19224
+ function resolveDependencyCatalogReferences(value, catalogs) {
19225
+ const dependencies = readRecord(value);
19226
+ if (!dependencies) {
19227
+ return value;
19228
+ }
19229
+ const resolved = {};
19230
+ for (const [name, rawDependency] of Object.entries(dependencies)) {
19231
+ if (typeof rawDependency === "string") {
19232
+ resolved[name] = resolveCatalogRange({
19233
+ name,
19234
+ range: rawDependency,
19235
+ catalogs
19236
+ });
19237
+ continue;
19238
+ }
19239
+ const dependency = readRecord(rawDependency);
19240
+ if (!dependency) {
19241
+ resolved[name] = rawDependency;
19242
+ continue;
19243
+ }
19244
+ const version = typeof dependency.version === "string" ? resolveCatalogRange({
19245
+ name,
19246
+ range: dependency.version,
19247
+ catalogs
19248
+ }) : dependency.version;
19249
+ const specifier = typeof dependency.specifier === "string" ? resolveCatalogRange({
19250
+ name,
19251
+ range: dependency.specifier,
19252
+ catalogs
19253
+ }) : dependency.specifier;
19254
+ resolved[name] = {
19255
+ ...dependency,
19256
+ ...version !== undefined ? { version } : {},
19257
+ ...specifier !== undefined ? { specifier } : {}
19258
+ };
19259
+ }
19260
+ return resolved;
19261
+ }
19262
+ function resolveCatalogRange(input) {
19263
+ const catalogName = parseCatalogReference(input.range);
19264
+ if (catalogName === undefined) {
19265
+ return input.range;
19266
+ }
19267
+ const catalog = catalogName === "" ? input.catalogs.defaultCatalog : input.catalogs.namedCatalogs.get(catalogName);
19268
+ return catalog?.[input.name] ?? input.range;
19269
+ }
19270
+ function parseCatalogReference(value) {
19271
+ if (value === "catalog:") {
19272
+ return "";
19273
+ }
19274
+ if (!value.startsWith("catalog:")) {
19275
+ return;
19276
+ }
19277
+ return value.slice("catalog:".length);
19278
+ }
19279
+ function collectRootDependencies4(importer, catalogs) {
18718
19280
  if (!importer) {
18719
19281
  return [];
18720
19282
  }
18721
- return collectDependencyEdges3(importer);
19283
+ return collectDependencyEdges3(catalogs, importer);
18722
19284
  }
18723
- function collectDependencyEdges3(...sources) {
19285
+ function collectDependencyEdges3(catalogs, ...sources) {
18724
19286
  return sources.flatMap((source) => [
18725
- ...dependencyEntries3(source.dependencies, "production"),
18726
- ...dependencyEntries3(source.devDependencies, "development"),
18727
- ...dependencyEntries3(source.optionalDependencies, "optional"),
18728
- ...dependencyEntries3(source.peerDependencies, "peer")
19287
+ ...dependencyEntries3(source.dependencies, "production", catalogs),
19288
+ ...dependencyEntries3(source.devDependencies, "development", catalogs),
19289
+ ...dependencyEntries3(source.optionalDependencies, "optional", catalogs),
19290
+ ...dependencyEntries3(source.peerDependencies, "peer", catalogs)
18729
19291
  ]);
18730
19292
  }
18731
- function dependencyEntries3(value, type) {
19293
+ function dependencyEntries3(value, type, catalogs) {
18732
19294
  return Object.entries(readImporterDependencyMap(value)).map(([name, range]) => ({
18733
19295
  name,
18734
- range,
19296
+ range: resolveCatalogRange({
19297
+ name,
19298
+ range,
19299
+ catalogs
19300
+ }),
18735
19301
  type
18736
19302
  }));
18737
19303
  }
@@ -18862,18 +19428,18 @@ function dependencyTypeRank4(type) {
18862
19428
  }
18863
19429
  }
18864
19430
  function readRecord(value) {
18865
- return isObjectRecord7(value) ? value : undefined;
19431
+ return isObjectRecord8(value) ? value : undefined;
18866
19432
  }
18867
- function isObjectRecord7(value) {
19433
+ function isObjectRecord8(value) {
18868
19434
  return typeof value === "object" && value !== null && !Array.isArray(value);
18869
19435
  }
18870
19436
 
18871
19437
  // src/graph/npm-yarn-lock.ts
18872
19438
  var yarnLockfileModule = __toESM(require_lockfile(), 1);
18873
- import { existsSync as existsSync3, readdirSync as readdirSync2, statSync as statSync4 } from "node:fs";
18874
- import path6 from "node:path";
19439
+ import { existsSync as existsSync4, readdirSync as readdirSync3, statSync as statSync4 } from "node:fs";
19440
+ import path7 from "node:path";
18875
19441
  var yarnLockfile = yarnLockfileModule;
18876
- function parseYarnLockfile(lockfilePath, packageJsonPath = path6.join(path6.dirname(lockfilePath), "package.json"), options = {}) {
19442
+ function parseYarnLockfile(lockfilePath, packageJsonPath = path7.join(path7.dirname(lockfilePath), "package.json"), options = {}) {
18877
19443
  const lockfileText = readInputTextFile({
18878
19444
  filePath: lockfilePath,
18879
19445
  maxBytes: options.lockfileMaxBytes ?? LOCKFILE_MAX_BYTES
@@ -18910,7 +19476,7 @@ function parseYarnLockfile(lockfilePath, packageJsonPath = path6.join(path6.dirn
18910
19476
  return parsedRootPackageJson;
18911
19477
  }
18912
19478
  const workspacePackageJsonTexts = readWorkspacePackageJsonTexts({
18913
- projectRoot: path6.dirname(packageJsonPath),
19479
+ projectRoot: path7.dirname(packageJsonPath),
18914
19480
  rootPackageJson: parsedRootPackageJson.value,
18915
19481
  lockfilePath,
18916
19482
  packageJsonMaxBytes: options.packageJsonMaxBytes ?? PACKAGE_JSON_MAX_BYTES
@@ -18986,7 +19552,7 @@ function parseYarnLockText(input) {
18986
19552
  function parsePackageJson(input, packageJsonPath) {
18987
19553
  try {
18988
19554
  const parsed = JSON.parse(input);
18989
- if (!isObjectRecord8(parsed)) {
19555
+ if (!isObjectRecord9(parsed)) {
18990
19556
  throw new Error("Expected package.json to contain an object.");
18991
19557
  }
18992
19558
  return ok(parsed);
@@ -19052,9 +19618,9 @@ function readWorkspacePackageJsonTexts(input) {
19052
19618
  function findYarnWorkspacePackageJsonPaths(input) {
19053
19619
  const locations = [];
19054
19620
  const seen = new Set;
19055
- const projectRoot = path6.resolve(input.projectRoot);
19621
+ const projectRoot = path7.resolve(input.projectRoot);
19056
19622
  const patterns = readWorkspacePatterns(input.workspaces);
19057
- const excludedWorkspacePaths = new Set(patterns.filter((pattern) => pattern.startsWith("!")).flatMap((pattern) => expandWorkspacePattern(projectRoot, pattern.slice(1))).filter((workspacePath) => isInsideDirectory(projectRoot, workspacePath)).map((workspacePath) => path6.resolve(workspacePath)));
19623
+ const excludedWorkspacePaths = new Set(patterns.filter((pattern) => pattern.startsWith("!")).flatMap((pattern) => expandWorkspacePattern(projectRoot, pattern.slice(1))).filter((workspacePath) => isInsideDirectory(projectRoot, workspacePath)).map((workspacePath) => path7.resolve(workspacePath)));
19058
19624
  for (const pattern of patterns) {
19059
19625
  if (pattern.startsWith("!")) {
19060
19626
  continue;
@@ -19063,15 +19629,15 @@ function findYarnWorkspacePackageJsonPaths(input) {
19063
19629
  if (!isInsideDirectory(projectRoot, workspacePath)) {
19064
19630
  continue;
19065
19631
  }
19066
- const packageJsonPath = path6.join(workspacePath, "package.json");
19067
- const relativePackageJsonPath = path6.relative(projectRoot, packageJsonPath).replace(/\\/g, "/");
19068
- if (seen.has(relativePackageJsonPath) || excludedWorkspacePaths.has(path6.resolve(workspacePath)) || !existsSync3(packageJsonPath)) {
19632
+ const packageJsonPath = path7.join(workspacePath, "package.json");
19633
+ const relativePackageJsonPath = path7.relative(projectRoot, packageJsonPath).replace(/\\/g, "/");
19634
+ if (seen.has(relativePackageJsonPath) || excludedWorkspacePaths.has(path7.resolve(workspacePath)) || !existsSync4(packageJsonPath)) {
19069
19635
  continue;
19070
19636
  }
19071
19637
  locations.push({
19072
19638
  packageJsonPath,
19073
19639
  relativePackageJsonPath,
19074
- workspacePath: path6.relative(projectRoot, workspacePath).replace(/\\/g, "/")
19640
+ workspacePath: path7.relative(projectRoot, workspacePath).replace(/\\/g, "/")
19075
19641
  });
19076
19642
  seen.add(relativePackageJsonPath);
19077
19643
  }
@@ -19082,7 +19648,7 @@ function readWorkspacePatterns(value) {
19082
19648
  if (Array.isArray(value)) {
19083
19649
  return value.filter((item) => typeof item === "string");
19084
19650
  }
19085
- if (isObjectRecord8(value) && Array.isArray(value.packages)) {
19651
+ if (isObjectRecord9(value) && Array.isArray(value.packages)) {
19086
19652
  return value.packages.filter((item) => typeof item === "string");
19087
19653
  }
19088
19654
  return [];
@@ -19111,17 +19677,17 @@ function expandWorkspaceSegments(currentPath, segments) {
19111
19677
  }
19112
19678
  if (segment.includes("*")) {
19113
19679
  const matcher = wildcardSegmentMatcher(segment);
19114
- return listChildDirectories(currentPath).filter((childPath) => matcher.test(path6.basename(childPath))).flatMap((childPath) => expandWorkspaceSegments(childPath, rest));
19680
+ return listChildDirectories(currentPath).filter((childPath) => matcher.test(path7.basename(childPath))).flatMap((childPath) => expandWorkspaceSegments(childPath, rest));
19115
19681
  }
19116
- return expandWorkspaceSegments(path6.join(currentPath, segment), rest);
19682
+ return expandWorkspaceSegments(path7.join(currentPath, segment), rest);
19117
19683
  }
19118
19684
  function isInsideDirectory(rootPath, candidatePath) {
19119
- const relativePath = path6.relative(rootPath, path6.resolve(candidatePath));
19120
- return relativePath === "" || relativePath !== ".." && !relativePath.startsWith(`..${path6.sep}`) && !path6.isAbsolute(relativePath);
19685
+ const relativePath = path7.relative(rootPath, path7.resolve(candidatePath));
19686
+ return relativePath === "" || relativePath !== ".." && !relativePath.startsWith(`..${path7.sep}`) && !path7.isAbsolute(relativePath);
19121
19687
  }
19122
19688
  function listChildDirectories(parentPath) {
19123
19689
  try {
19124
- return readdirSync2(parentPath, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name !== "node_modules").map((entry) => path6.join(parentPath, entry.name));
19690
+ return readdirSync3(parentPath, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name !== "node_modules").map((entry) => path7.join(parentPath, entry.name));
19125
19691
  } catch {
19126
19692
  return [];
19127
19693
  }
@@ -19141,17 +19707,20 @@ function readPackageName2(packageJson) {
19141
19707
  return typeof packageJson.name === "string" && packageJson.name !== "" ? packageJson.name : undefined;
19142
19708
  }
19143
19709
  function parseLockfile(input, lockfilePath) {
19710
+ if (hasMergeConflictMarkers(input)) {
19711
+ return err(createError({
19712
+ code: "YARN_LOCK_PARSE_FAILED",
19713
+ category: "unsupported_input",
19714
+ message: "Failed to parse yarn.lock because it contains unresolved merge conflicts.",
19715
+ details: {
19716
+ lockfilePath
19717
+ }
19718
+ }));
19719
+ }
19720
+ if (isYarnBerryLockfile(input)) {
19721
+ return parseBerryLockfile(input, lockfilePath);
19722
+ }
19144
19723
  try {
19145
- if (hasMergeConflictMarkers(input)) {
19146
- return err(createError({
19147
- code: "YARN_LOCK_PARSE_FAILED",
19148
- category: "unsupported_input",
19149
- message: "Failed to parse yarn.lock because it contains unresolved merge conflicts.",
19150
- details: {
19151
- lockfilePath
19152
- }
19153
- }));
19154
- }
19155
19724
  const parsed = yarnLockfile.parse(input);
19156
19725
  if (parsed.type === "conflict") {
19157
19726
  return err(createError({
@@ -19163,12 +19732,47 @@ function parseLockfile(input, lockfilePath) {
19163
19732
  }
19164
19733
  }));
19165
19734
  }
19166
- return ok(parsed.object);
19735
+ return ok({
19736
+ format: "classic",
19737
+ entries: parsed.object
19738
+ });
19167
19739
  } catch (cause) {
19168
19740
  return err(createError({
19169
19741
  code: "YARN_LOCK_PARSE_FAILED",
19170
19742
  category: "unsupported_input",
19171
- message: "Failed to parse yarn.lock. Ohrisk currently supports Yarn v1 lockfiles.",
19743
+ message: "Failed to parse yarn.lock. Ohrisk expects a Yarn classic or Berry lockfile.",
19744
+ details: {
19745
+ lockfilePath,
19746
+ cause: cause instanceof Error ? cause.message : String(cause)
19747
+ }
19748
+ }));
19749
+ }
19750
+ }
19751
+ function isYarnBerryLockfile(input) {
19752
+ return /^__metadata:\s*$/m.test(input);
19753
+ }
19754
+ function parseBerryLockfile(input, lockfilePath) {
19755
+ try {
19756
+ const parsed = $parse(input);
19757
+ if (!isObjectRecord9(parsed)) {
19758
+ throw new Error("Expected a YAML mapping at the document root.");
19759
+ }
19760
+ const entries = {};
19761
+ for (const [key, value] of Object.entries(parsed)) {
19762
+ if (key === "__metadata" || !isObjectRecord9(value)) {
19763
+ continue;
19764
+ }
19765
+ entries[key] = value;
19766
+ }
19767
+ return ok({
19768
+ format: "berry",
19769
+ entries
19770
+ });
19771
+ } catch (cause) {
19772
+ return err(createError({
19773
+ code: "YARN_LOCK_PARSE_FAILED",
19774
+ category: "unsupported_input",
19775
+ message: "Failed to parse Yarn Berry lockfile.",
19172
19776
  details: {
19173
19777
  lockfilePath,
19174
19778
  cause: cause instanceof Error ? cause.message : String(cause)
@@ -19181,12 +19785,12 @@ function hasMergeConflictMarkers(input) {
19181
19785
  }
19182
19786
  function parsePackageRecords4(lockfile) {
19183
19787
  const records = [];
19184
- for (const [key, entry] of Object.entries(lockfile)) {
19788
+ for (const [key, entry] of Object.entries(lockfile.entries)) {
19185
19789
  if (typeof entry.version !== "string" || entry.version === "") {
19186
19790
  continue;
19187
19791
  }
19188
19792
  const descriptors = splitDescriptorKey(key);
19189
- const identity2 = descriptors.map(parseDescriptor).find(Boolean);
19793
+ const identity2 = lockfile.format === "berry" ? readBerryPackageIdentity({ key, entry }) : descriptors.map(parseDescriptor).find(Boolean);
19190
19794
  if (!identity2) {
19191
19795
  continue;
19192
19796
  }
@@ -19194,7 +19798,10 @@ function parsePackageRecords4(lockfile) {
19194
19798
  const integrity = typeof entry.integrity === "string" && entry.integrity !== "" ? entry.integrity : undefined;
19195
19799
  records.push({
19196
19800
  key,
19197
- descriptors,
19801
+ descriptors: descriptorIndexKeys({
19802
+ descriptors,
19803
+ format: lockfile.format
19804
+ }),
19198
19805
  name: identity2.name,
19199
19806
  version: entry.version,
19200
19807
  id: `${identity2.name}@${entry.version}`,
@@ -19208,8 +19815,26 @@ function parsePackageRecords4(lockfile) {
19208
19815
  function splitDescriptorKey(key) {
19209
19816
  return key.split(/,\s*/).map((descriptor) => descriptor.trim()).filter(Boolean);
19210
19817
  }
19818
+ function descriptorIndexKeys(input) {
19819
+ const keys = new Set;
19820
+ for (const descriptor of input.descriptors) {
19821
+ const unquoted = unquoteDescriptor(descriptor);
19822
+ keys.add(unquoted);
19823
+ const parsed = input.format === "berry" ? parseBerryDescriptor(unquoted) : parseDescriptor(unquoted);
19824
+ if (!parsed) {
19825
+ continue;
19826
+ }
19827
+ keys.add(`${parsed.name}@${parsed.range}`);
19828
+ keys.add(`${parsed.name}@npm:${parsed.range}`);
19829
+ }
19830
+ return [...keys];
19831
+ }
19211
19832
  function parseDescriptor(descriptor) {
19212
- const unquoted = descriptor.replace(/^"|"$/g, "");
19833
+ const unquoted = unquoteDescriptor(descriptor);
19834
+ const berryDescriptor = parseBerryDescriptor(unquoted);
19835
+ if (berryDescriptor) {
19836
+ return berryDescriptor;
19837
+ }
19213
19838
  const aliasMarker = "@npm:";
19214
19839
  const aliasIndex = unquoted.indexOf(aliasMarker);
19215
19840
  if (aliasIndex > 0) {
@@ -19225,6 +19850,89 @@ function parseDescriptor(descriptor) {
19225
19850
  }
19226
19851
  return { name: parsed.name, range: parsed.reference };
19227
19852
  }
19853
+ function parseBerryDescriptor(descriptor) {
19854
+ const npmLocator = parseBerryNpmLocator(descriptor);
19855
+ if (npmLocator) {
19856
+ const alias = parseNpmPackageReference(`npm:${npmLocator.reference}`);
19857
+ return alias ? { name: alias.name, range: alias.reference } : { name: npmLocator.name, range: npmLocator.reference };
19858
+ }
19859
+ const patchLocator = parseBerryPatchLocator(descriptor);
19860
+ if (patchLocator) {
19861
+ return patchLocator;
19862
+ }
19863
+ return;
19864
+ }
19865
+ function readBerryPackageIdentity(input) {
19866
+ const resolution = typeof input.entry.resolution === "string" ? input.entry.resolution : undefined;
19867
+ const parsedResolution = resolution ? parseBerryResolution(resolution) : undefined;
19868
+ if (parsedResolution) {
19869
+ return parsedResolution;
19870
+ }
19871
+ const descriptorIdentity = splitDescriptorKey(input.key).map((descriptor) => parseBerryDescriptor(unquoteDescriptor(descriptor))).find(Boolean);
19872
+ return descriptorIdentity ? { name: descriptorIdentity.name, version: descriptorIdentity.range } : undefined;
19873
+ }
19874
+ function parseBerryResolution(value) {
19875
+ const unquoted = unquoteDescriptor(value);
19876
+ const npmLocator = parseBerryNpmLocator(unquoted);
19877
+ if (npmLocator) {
19878
+ return {
19879
+ name: npmLocator.name,
19880
+ version: npmLocator.reference
19881
+ };
19882
+ }
19883
+ const patchLocator = parseBerryPatchLocator(unquoted);
19884
+ if (patchLocator) {
19885
+ return {
19886
+ name: patchLocator.name,
19887
+ version: patchLocator.range
19888
+ };
19889
+ }
19890
+ return;
19891
+ }
19892
+ function parseBerryNpmLocator(value) {
19893
+ const marker = "@npm:";
19894
+ const index = value.indexOf(marker);
19895
+ if (index <= 0) {
19896
+ return;
19897
+ }
19898
+ const name = value.slice(0, index);
19899
+ const reference = value.slice(index + marker.length);
19900
+ if (!isValidNpmPackageName(name) || reference === "") {
19901
+ return;
19902
+ }
19903
+ return { name, reference };
19904
+ }
19905
+ function parseBerryPatchLocator(value) {
19906
+ const marker = "@patch:";
19907
+ const index = value.indexOf(marker);
19908
+ if (index <= 0) {
19909
+ return;
19910
+ }
19911
+ const patchedLocator = value.slice(index + marker.length).split("#")[0]?.split("::")[0];
19912
+ if (!patchedLocator) {
19913
+ return;
19914
+ }
19915
+ const decodedLocator = safeDecodeURIComponent(patchedLocator);
19916
+ const npmLocator = parseBerryNpmLocator(decodedLocator);
19917
+ if (!npmLocator) {
19918
+ return;
19919
+ }
19920
+ const alias = parseNpmPackageReference(`npm:${npmLocator.reference}`);
19921
+ return alias ? { name: alias.name, range: alias.reference } : { name: npmLocator.name, range: npmLocator.reference };
19922
+ }
19923
+ function safeDecodeURIComponent(value) {
19924
+ try {
19925
+ return decodeURIComponent(value);
19926
+ } catch {
19927
+ return value;
19928
+ }
19929
+ }
19930
+ function unquoteDescriptor(value) {
19931
+ return value.replace(/^"|"$/g, "");
19932
+ }
19933
+ function isValidNpmPackageName(value) {
19934
+ return /^(?:@[^/]+\/)?[^/@][^@]*$/.test(value);
19935
+ }
19228
19936
  function collectRootDependencies5(packageJson) {
19229
19937
  return [
19230
19938
  ...dependencyEntries4(packageJson.dependencies, "production"),
@@ -19247,7 +19955,7 @@ function dependencyEntries4(value, type) {
19247
19955
  }));
19248
19956
  }
19249
19957
  function readDependencyMap3(value) {
19250
- if (!isObjectRecord8(value)) {
19958
+ if (!isObjectRecord9(value)) {
19251
19959
  return {};
19252
19960
  }
19253
19961
  const dependencies = {};
@@ -19277,10 +19985,28 @@ function indexPackagesByName3(records) {
19277
19985
  return index;
19278
19986
  }
19279
19987
  function resolvePackageRecord4(input) {
19280
- const descriptor = `${input.name}@${input.range}`;
19281
19988
  const reference = resolveNpmDependencyReference(input.name, input.range);
19282
19989
  const candidates = input.nameIndex.get(reference.lookupName) ?? [];
19283
- return input.descriptorIndex.get(descriptor) ?? (candidates.length === 1 ? candidates[0] : undefined) ?? candidates.find((candidate) => candidate.version === reference.lookupRange) ?? undefined;
19990
+ return dependencyDescriptorCandidates({
19991
+ name: input.name,
19992
+ range: input.range,
19993
+ reference
19994
+ }).map((descriptor) => input.descriptorIndex.get(descriptor)).find((record) => record !== undefined) ?? (candidates.length === 1 ? candidates[0] : undefined) ?? candidates.find((candidate) => candidate.version === reference.lookupRange) ?? undefined;
19995
+ }
19996
+ function dependencyDescriptorCandidates(input) {
19997
+ const candidates = new Set;
19998
+ candidates.add(`${input.name}@${input.range}`);
19999
+ candidates.add(`${input.reference.lookupName}@${input.reference.lookupRange}`);
20000
+ candidates.add(`${input.name}@npm:${input.range}`);
20001
+ candidates.add(`${input.reference.lookupName}@npm:${input.reference.lookupRange}`);
20002
+ if (input.range.startsWith("npm:")) {
20003
+ const bareRange = input.range.slice("npm:".length);
20004
+ candidates.add(`${input.name}@${bareRange}`);
20005
+ candidates.add(`${input.name}@npm:${bareRange}`);
20006
+ candidates.add(`${input.reference.lookupName}@${bareRange}`);
20007
+ candidates.add(`${input.reference.lookupName}@npm:${bareRange}`);
20008
+ }
20009
+ return [...candidates].filter((candidate) => !candidate.endsWith("@"));
19284
20010
  }
19285
20011
  function walkDependency5(input) {
19286
20012
  if (input.seen.has(input.record.key)) {
@@ -19367,7 +20093,7 @@ function dependencyTypeRank5(type) {
19367
20093
  return 0;
19368
20094
  }
19369
20095
  }
19370
- function isObjectRecord8(value) {
20096
+ function isObjectRecord9(value) {
19371
20097
  return typeof value === "object" && value !== null && !Array.isArray(value);
19372
20098
  }
19373
20099
 
@@ -20051,13 +20777,13 @@ function severityRank2(severity) {
20051
20777
  }
20052
20778
 
20053
20779
  // src/policy/waivers.ts
20054
- import { existsSync as existsSync4 } from "node:fs";
20055
- import path7 from "node:path";
20780
+ import { existsSync as existsSync5 } from "node:fs";
20781
+ import path8 from "node:path";
20056
20782
  var DEFAULT_WAIVER_FILE_NAME = ".ohrisk-waivers.json";
20057
20783
  var WAIVER_FILE_MAX_BYTES = 1024 * 1024;
20058
20784
  function readRiskWaivers(projectRoot, options) {
20059
- const waiverPath = path7.join(projectRoot, DEFAULT_WAIVER_FILE_NAME);
20060
- if (!existsSync4(waiverPath)) {
20785
+ const waiverPath = path8.join(projectRoot, DEFAULT_WAIVER_FILE_NAME);
20786
+ if (!existsSync5(waiverPath)) {
20061
20787
  return ok([]);
20062
20788
  }
20063
20789
  const text = readTextFileWithLimit({
@@ -20202,7 +20928,7 @@ function isRecord2(value) {
20202
20928
  }
20203
20929
 
20204
20930
  // src/report/cyclonedx-report.ts
20205
- import path8 from "node:path";
20931
+ import path9 from "node:path";
20206
20932
  function renderCycloneDxReport(input) {
20207
20933
  const licensesByPackageId = new Map(input.normalizedLicenses.map((license) => [license.packageId, license]));
20208
20934
  const findingsByPackageId = new Map(input.riskFindings.map((finding) => [finding.packageId, finding]));
@@ -20255,11 +20981,11 @@ function renderCycloneDxReport(input) {
20255
20981
  }, null, 2);
20256
20982
  }
20257
20983
  function projectRelativePath(projectRoot, targetPath) {
20258
- const relativePath = path8.relative(projectRoot, targetPath);
20259
- if (relativePath && !relativePath.startsWith("..") && !path8.isAbsolute(relativePath)) {
20984
+ const relativePath = path9.relative(projectRoot, targetPath);
20985
+ if (relativePath && !relativePath.startsWith("..") && !path9.isAbsolute(relativePath)) {
20260
20986
  return relativePath.replace(/\\/g, "/");
20261
20987
  }
20262
- return path8.basename(targetPath);
20988
+ return path9.basename(targetPath);
20263
20989
  }
20264
20990
  function renderComponent(input) {
20265
20991
  const licenses = input.license ? renderLicenses(input.license) : [];
@@ -20368,8 +21094,8 @@ function directChildRefsByNodeId(nodes) {
20368
21094
  const nodeById = new Map(nodes.map((node) => [node.id, node]));
20369
21095
  const childIdsByNodeId = new Map;
20370
21096
  for (const candidate of nodes) {
20371
- for (const path9 of candidate.paths) {
20372
- const packagePath = path9.map(packageIdFromPathSegment);
21097
+ for (const path10 of candidate.paths) {
21098
+ const packagePath = path10.map(packageIdFromPathSegment);
20373
21099
  for (let index = 0;index < packagePath.length - 1; index += 1) {
20374
21100
  const parentId = packagePath[index];
20375
21101
  const childId = packagePath[index + 1];
@@ -20625,7 +21351,7 @@ function formatNormalizedExpression(license) {
20625
21351
  }
20626
21352
 
20627
21353
  // src/report/sarif-report.ts
20628
- import path9 from "node:path";
21354
+ import path10 from "node:path";
20629
21355
  var SARIF_SCHEMA_URL = "https://json.schemastore.org/sarif-2.1.0.json";
20630
21356
  var RULES = [
20631
21357
  ruleFor("high", "High license risk", "A dependency has license evidence that is high risk for the selected profile."),
@@ -20635,7 +21361,7 @@ var RULES = [
20635
21361
  ];
20636
21362
  var RULE_INDEX_BY_ID = new Map(RULES.map((rule, index) => [rule.id, index]));
20637
21363
  function renderSarifReport(input) {
20638
- const lockfileUri = path9.relative(input.project.rootDir, input.project.lockfile.path).replace(/\\/g, "/") || path9.basename(input.project.lockfile.path);
21364
+ const lockfileUri = path10.relative(input.project.rootDir, input.project.lockfile.path).replace(/\\/g, "/") || path10.basename(input.project.lockfile.path);
20639
21365
  return JSON.stringify({
20640
21366
  $schema: SARIF_SCHEMA_URL,
20641
21367
  version: "2.1.0",
@@ -20814,7 +21540,7 @@ function securitySeverityFor(severity) {
20814
21540
  }
20815
21541
 
20816
21542
  // src/report/scan-report.ts
20817
- import path10 from "node:path";
21543
+ import path11 from "node:path";
20818
21544
  function renderScanReport(input) {
20819
21545
  const summary = buildScanSummary(input);
20820
21546
  const nextAction = nextActionFor2(input.riskFindings);
@@ -20851,7 +21577,7 @@ function renderScanReport(input) {
20851
21577
  return [
20852
21578
  "Ohrisk scan",
20853
21579
  `Project: ${input.project.rootDir}`,
20854
- `Lockfile: ${path10.basename(input.project.lockfile.path)} (${input.project.lockfile.kind})`,
21580
+ `Lockfile: ${path11.basename(input.project.lockfile.path)} (${input.project.lockfile.kind})`,
20855
21581
  `Profile: ${input.profile}`,
20856
21582
  `Production only: ${input.prodOnly ? "yes" : "no"}`,
20857
21583
  `Dependencies: ${summary.dependencyGraph.total} total, ${summary.dependencyGraph.direct} direct, ${summary.dependencyGraph.transitive} transitive`,
@@ -20885,7 +21611,7 @@ function renderMarkdownReport2(input, summary) {
20885
21611
  "# Ohrisk scan",
20886
21612
  "",
20887
21613
  `- Project: ${formatMarkdownInlineCode(markdownProjectLabel(input))}`,
20888
- `- Lockfile: ${formatMarkdownInlineCode(path10.basename(input.project.lockfile.path))} (${formatMarkdownInlineCode(input.project.lockfile.kind)})`,
21614
+ `- Lockfile: ${formatMarkdownInlineCode(path11.basename(input.project.lockfile.path))} (${formatMarkdownInlineCode(input.project.lockfile.kind)})`,
20889
21615
  `- Profile: ${formatMarkdownInlineCode(input.profile)}`,
20890
21616
  `- Production only: ${formatMarkdownInlineCode(input.prodOnly ? "yes" : "no")}`,
20891
21617
  `- Dependencies: ${formatMarkdownInlineCode(`${summary.dependencyGraph.total} total`)}, ${formatMarkdownInlineCode(`${summary.dependencyGraph.direct} direct`)}, ${formatMarkdownInlineCode(`${summary.dependencyGraph.transitive} transitive`)}`,
@@ -21154,11 +21880,11 @@ function nextActionFor2(findings) {
21154
21880
 
21155
21881
  // src/report/write-output.ts
21156
21882
  import { mkdirSync, writeFileSync } from "node:fs";
21157
- import path11 from "node:path";
21883
+ import path12 from "node:path";
21158
21884
  var writeReportFile = (input) => {
21159
- const resolvedPath = path11.resolve(input.cwd, input.outputPath);
21885
+ const resolvedPath = path12.resolve(input.cwd, input.outputPath);
21160
21886
  try {
21161
- mkdirSync(path11.dirname(resolvedPath), { recursive: true });
21887
+ mkdirSync(path12.dirname(resolvedPath), { recursive: true });
21162
21888
  writeFileSync(resolvedPath, `${input.contents}
21163
21889
  `, "utf8");
21164
21890
  return ok(resolvedPath);
@@ -21177,8 +21903,8 @@ var writeReportFile = (input) => {
21177
21903
  };
21178
21904
 
21179
21905
  // src/project/discover.ts
21180
- import { existsSync as existsSync5, statSync as statSync5 } from "node:fs";
21181
- import path12 from "node:path";
21906
+ import { existsSync as existsSync6, statSync as statSync5 } from "node:fs";
21907
+ import path13 from "node:path";
21182
21908
  var SUPPORTED_LOCKFILES = {
21183
21909
  "bun.lock": "bun",
21184
21910
  "package-lock.json": "package-lock",
@@ -21200,9 +21926,9 @@ var KNOWN_PROJECT_MANIFESTS = [
21200
21926
  "deno.json",
21201
21927
  "deno.jsonc"
21202
21928
  ];
21203
- var SUPPORTED_LOCKFILE_MESSAGE = "Ohrisk currently supports bun.lock, package-lock.json, npm-shrinkwrap.json, pnpm-lock.yaml, deno.lock, and Yarn v1 yarn.lock.";
21929
+ var SUPPORTED_LOCKFILE_MESSAGE = "Ohrisk currently supports bun.lock, package-lock.json, npm-shrinkwrap.json, pnpm-lock.yaml, deno.lock, and Yarn classic/Berry yarn.lock.";
21204
21930
  function discoverProject(options = {}) {
21205
- const startDir = path12.resolve(options.cwd ?? process.cwd());
21931
+ const startDir = path13.resolve(options.cwd ?? process.cwd());
21206
21932
  try {
21207
21933
  if (options.lockfilePath) {
21208
21934
  return discoverExplicitLockfile({
@@ -21212,7 +21938,7 @@ function discoverProject(options = {}) {
21212
21938
  }
21213
21939
  for (const dir of ancestorsFrom(startDir)) {
21214
21940
  const lockfiles = findKnownLockfiles(dir);
21215
- const hasProjectManifest = KNOWN_PROJECT_MANIFESTS.some((manifest) => existsSync5(path12.join(dir, manifest)));
21941
+ const hasProjectManifest = KNOWN_PROJECT_MANIFESTS.some((manifest) => existsSync6(path13.join(dir, manifest)));
21216
21942
  if (lockfiles.length === 0) {
21217
21943
  if (hasProjectManifest) {
21218
21944
  return err(createError({
@@ -21259,7 +21985,7 @@ function discoverProject(options = {}) {
21259
21985
  rootDir: dir,
21260
21986
  lockfile: {
21261
21987
  kind,
21262
- path: path12.join(dir, lockfileName)
21988
+ path: path13.join(dir, lockfileName)
21263
21989
  }
21264
21990
  });
21265
21991
  }
@@ -21285,8 +22011,8 @@ function discoverProject(options = {}) {
21285
22011
  }));
21286
22012
  }
21287
22013
  function discoverExplicitLockfile(input) {
21288
- const lockfilePath = path12.resolve(input.cwd, input.lockfilePath);
21289
- const lockfileName = path12.basename(lockfilePath);
22014
+ const lockfilePath = path13.resolve(input.cwd, input.lockfilePath);
22015
+ const lockfileName = path13.basename(lockfilePath);
21290
22016
  const kind = SUPPORTED_LOCKFILES[lockfileName];
21291
22017
  if (!kind) {
21292
22018
  return err(createError({
@@ -21299,7 +22025,7 @@ function discoverExplicitLockfile(input) {
21299
22025
  }
21300
22026
  }));
21301
22027
  }
21302
- if (!existsSync5(lockfilePath)) {
22028
+ if (!existsSync6(lockfilePath)) {
21303
22029
  return err(createError({
21304
22030
  code: "LOCKFILE_NOT_FOUND",
21305
22031
  category: "invalid_input",
@@ -21320,7 +22046,7 @@ function discoverExplicitLockfile(input) {
21320
22046
  }));
21321
22047
  }
21322
22048
  return ok({
21323
- rootDir: path12.dirname(lockfilePath),
22049
+ rootDir: path13.dirname(lockfilePath),
21324
22050
  lockfile: {
21325
22051
  kind,
21326
22052
  path: lockfilePath
@@ -21328,7 +22054,7 @@ function discoverExplicitLockfile(input) {
21328
22054
  });
21329
22055
  }
21330
22056
  function findKnownLockfiles(dir) {
21331
- return KNOWN_LOCKFILES.filter((lockfile) => isFile(path12.join(dir, lockfile)));
22057
+ return KNOWN_LOCKFILES.filter((lockfile) => isFile(path13.join(dir, lockfile)));
21332
22058
  }
21333
22059
  function isFile(pathname) {
21334
22060
  try {
@@ -21342,7 +22068,7 @@ function ancestorsFrom(startDir) {
21342
22068
  let current = startDir;
21343
22069
  while (true) {
21344
22070
  dirs.push(current);
21345
- const parent = path12.dirname(current);
22071
+ const parent = path13.dirname(current);
21346
22072
  if (parent === current) {
21347
22073
  return dirs;
21348
22074
  }
@@ -21385,7 +22111,7 @@ async function runDiff(command, io) {
21385
22111
  io.stderr(formatError(currentProject.error));
21386
22112
  return exitCodeForError(currentProject.error);
21387
22113
  }
21388
- const relativeLockfilePath = path13.relative(currentProject.value.project.rootDir, currentProject.value.project.lockfile.path);
22114
+ const relativeLockfilePath = path14.relative(currentProject.value.project.rootDir, currentProject.value.project.lockfile.path);
21389
22115
  const readRefFile = io.readRefFile ?? readGitRefFile;
21390
22116
  const baselineLockfile = readRefFile({
21391
22117
  projectRoot: currentProject.value.project.rootDir,
@@ -21415,13 +22141,25 @@ async function runDiff(command, io) {
21415
22141
  io.stderr(formatError(baselineWorkspacePackageJsons.error));
21416
22142
  return exitCodeForError(baselineWorkspacePackageJsons.error);
21417
22143
  }
22144
+ const baselinePnpmWorkspace = currentProject.value.project.lockfile.kind === "pnpm-lock" ? readOptionalBaselineFile({
22145
+ projectRoot: currentProject.value.project.rootDir,
22146
+ baselineRef: command.baselineRef,
22147
+ relativePath: "pnpm-workspace.yaml",
22148
+ readRefFile
22149
+ }) : ok(undefined);
22150
+ if (isErr(baselinePnpmWorkspace)) {
22151
+ io.stderr(formatError(baselinePnpmWorkspace.error));
22152
+ return exitCodeForError(baselinePnpmWorkspace.error);
22153
+ }
21418
22154
  const baselineGraph = parseLockfileTextForKind({
21419
22155
  kind: currentProject.value.project.lockfile.kind,
21420
22156
  text: baselineLockfile.value,
21421
22157
  lockfilePath: `${command.baselineRef}:${relativeLockfilePath}`,
21422
22158
  packageJsonText: baselinePackageJson?.value,
21423
22159
  packageJsonPath: `${command.baselineRef}:package.json`,
21424
- workspacePackageJsonTexts: baselineWorkspacePackageJsons.value
22160
+ workspacePackageJsonTexts: baselineWorkspacePackageJsons.value,
22161
+ pnpmWorkspaceText: baselinePnpmWorkspace.value,
22162
+ pnpmWorkspacePath: `${command.baselineRef}:pnpm-workspace.yaml`
21425
22163
  });
21426
22164
  if (isErr(baselineGraph)) {
21427
22165
  io.stderr(formatError(baselineGraph.error));
@@ -21688,7 +22426,10 @@ function parseLockfileTextForKind(input) {
21688
22426
  case "npm-shrinkwrap":
21689
22427
  return parsePackageLockText(input.text, input.lockfilePath);
21690
22428
  case "pnpm-lock":
21691
- return parsePnpmLockText(input.text, input.lockfilePath);
22429
+ return parsePnpmLockText(input.text, input.lockfilePath, {
22430
+ workspaceText: input.pnpmWorkspaceText,
22431
+ workspacePath: input.pnpmWorkspacePath
22432
+ });
21692
22433
  case "deno-lock":
21693
22434
  return parseDenoLockText(input.text, input.lockfilePath);
21694
22435
  case "yarn-lock":
@@ -21730,6 +22471,20 @@ function readBaselineYarnWorkspacePackageJsons(input) {
21730
22471
  }
21731
22472
  return ok(packageJsons);
21732
22473
  }
22474
+ function readOptionalBaselineFile(input) {
22475
+ const result = input.readRefFile({
22476
+ projectRoot: input.projectRoot,
22477
+ ref: input.baselineRef,
22478
+ relativePath: input.relativePath
22479
+ });
22480
+ if (!isErr(result)) {
22481
+ return ok(result.value);
22482
+ }
22483
+ if (result.error.code === "GIT_REF_FILE_NOT_FOUND") {
22484
+ return ok(undefined);
22485
+ }
22486
+ return err(result.error);
22487
+ }
21733
22488
  function tryParseObject(input) {
21734
22489
  try {
21735
22490
  const parsed = JSON.parse(input);
@@ -21931,7 +22686,7 @@ function isCliEntrypoint(metaUrl, argvPath) {
21931
22686
  try {
21932
22687
  return realpathSync2(fileURLToPath2(metaUrl)) === realpathSync2(argvPath);
21933
22688
  } catch {
21934
- return path13.resolve(fileURLToPath2(metaUrl)) === path13.resolve(argvPath);
22689
+ return path14.resolve(fileURLToPath2(metaUrl)) === path14.resolve(argvPath);
21935
22690
  }
21936
22691
  }
21937
22692
  function defaultIO() {