@pnpm/exe 11.0.0-alpha.11 → 11.0.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -193,11 +193,13 @@ export class Minimatch {
193
193
  isWindows;
194
194
  platform;
195
195
  windowsNoMagicRoot;
196
+ maxGlobstarRecursion;
196
197
  regexp;
197
198
  constructor(pattern, options = {}) {
198
199
  assertValidPattern(pattern);
199
200
  options = options || {};
200
201
  this.options = options;
202
+ this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200;
201
203
  this.pattern = pattern;
202
204
  this.platform = options.platform || defaultPlatform;
203
205
  this.isWindows = this.platform === 'win32';
@@ -602,7 +604,8 @@ export class Minimatch {
602
604
  // out of pattern, then that's fine, as long as all
603
605
  // the parts match.
604
606
  matchOne(file, pattern, partial = false) {
605
- const options = this.options;
607
+ let fileStartIndex = 0;
608
+ let patternStartIndex = 0;
606
609
  // UNC paths like //?/X:/... can match X:/... and vice versa
607
610
  // Drive letters in absolute drive or unc paths are always compared
608
611
  // case-insensitively.
@@ -631,14 +634,11 @@ export class Minimatch {
631
634
  file[fdi],
632
635
  pattern[pdi],
633
636
  ];
637
+ // start matching at the drive letter index of each
634
638
  if (fd.toLowerCase() === pd.toLowerCase()) {
635
639
  pattern[pdi] = fd;
636
- if (pdi > fdi) {
637
- pattern = pattern.slice(pdi);
638
- }
639
- else if (fdi > pdi) {
640
- file = file.slice(fdi);
641
- }
640
+ patternStartIndex = pdi;
641
+ fileStartIndex = fdi;
642
642
  }
643
643
  }
644
644
  }
@@ -648,99 +648,185 @@ export class Minimatch {
648
648
  if (optimizationLevel >= 2) {
649
649
  file = this.levelTwoFileOptimize(file);
650
650
  }
651
- this.debug('matchOne', this, { file, pattern });
652
- this.debug('matchOne', file.length, pattern.length);
653
- for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
651
+ if (pattern.includes(GLOBSTAR)) {
652
+ return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex);
653
+ }
654
+ return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex);
655
+ }
656
+ #matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
657
+ // split the pattern into head, tail, and middle of ** delimited parts
658
+ const firstgs = pattern.indexOf(GLOBSTAR, patternIndex);
659
+ const lastgs = pattern.lastIndexOf(GLOBSTAR);
660
+ // split the pattern up into globstar-delimited sections
661
+ // the tail has to be at the end, and the others just have
662
+ // to be found in order from the head.
663
+ const [head, body, tail] = partial ? [
664
+ pattern.slice(patternIndex, firstgs),
665
+ pattern.slice(firstgs + 1),
666
+ [],
667
+ ] : [
668
+ pattern.slice(patternIndex, firstgs),
669
+ pattern.slice(firstgs + 1, lastgs),
670
+ pattern.slice(lastgs + 1),
671
+ ];
672
+ // check the head, from the current file/pattern index.
673
+ if (head.length) {
674
+ const fileHead = file.slice(fileIndex, fileIndex + head.length);
675
+ if (!this.#matchOne(fileHead, head, partial, 0, 0)) {
676
+ return false;
677
+ }
678
+ fileIndex += head.length;
679
+ patternIndex += head.length;
680
+ }
681
+ // now we know the head matches!
682
+ // if the last portion is not empty, it MUST match the end
683
+ // check the tail
684
+ let fileTailMatch = 0;
685
+ if (tail.length) {
686
+ // if head + tail > file, then we cannot possibly match
687
+ if (tail.length + fileIndex > file.length)
688
+ return false;
689
+ // try to match the tail
690
+ let tailStart = file.length - tail.length;
691
+ if (this.#matchOne(file, tail, partial, tailStart, 0)) {
692
+ fileTailMatch = tail.length;
693
+ }
694
+ else {
695
+ // affordance for stuff like a/**/* matching a/b/
696
+ // if the last file portion is '', and there's more to the pattern
697
+ // then try without the '' bit.
698
+ if (file[file.length - 1] !== '' ||
699
+ fileIndex + tail.length === file.length) {
700
+ return false;
701
+ }
702
+ tailStart--;
703
+ if (!this.#matchOne(file, tail, partial, tailStart, 0)) {
704
+ return false;
705
+ }
706
+ fileTailMatch = tail.length + 1;
707
+ }
708
+ }
709
+ // now we know the tail matches!
710
+ // the middle is zero or more portions wrapped in **, possibly
711
+ // containing more ** sections.
712
+ // so a/**/b/**/c/**/d has become **/b/**/c/**
713
+ // if it's empty, it means a/**/b, just verify we have no bad dots
714
+ // if there's no tail, so it ends on /**, then we must have *something*
715
+ // after the head, or it's not a matc
716
+ if (!body.length) {
717
+ let sawSome = !!fileTailMatch;
718
+ for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
719
+ const f = String(file[i]);
720
+ sawSome = true;
721
+ if (f === '.' ||
722
+ f === '..' ||
723
+ (!this.options.dot && f.startsWith('.'))) {
724
+ return false;
725
+ }
726
+ }
727
+ // in partial mode, we just need to get past all file parts
728
+ return partial || sawSome;
729
+ }
730
+ // now we know that there's one or more body sections, which can
731
+ // be matched anywhere from the 0 index (because the head was pruned)
732
+ // through to the length-fileTailMatch index.
733
+ // split the body up into sections, and note the minimum index it can
734
+ // be found at (start with the length of all previous segments)
735
+ // [section, before, after]
736
+ const bodySegments = [[[], 0]];
737
+ let currentBody = bodySegments[0];
738
+ let nonGsParts = 0;
739
+ const nonGsPartsSums = [0];
740
+ for (const b of body) {
741
+ if (b === GLOBSTAR) {
742
+ nonGsPartsSums.push(nonGsParts);
743
+ currentBody = [[], 0];
744
+ bodySegments.push(currentBody);
745
+ }
746
+ else {
747
+ currentBody[0].push(b);
748
+ nonGsParts++;
749
+ }
750
+ }
751
+ let i = bodySegments.length - 1;
752
+ const fileLength = file.length - fileTailMatch;
753
+ for (const b of bodySegments) {
754
+ b[1] = fileLength - (nonGsPartsSums[i--] + b[0].length);
755
+ }
756
+ return !!this.#matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
757
+ }
758
+ // return false for "nope, not matching"
759
+ // return null for "not matching, cannot keep trying"
760
+ #matchGlobStarBodySections(file,
761
+ // pattern section, last possible position for it
762
+ bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
763
+ // take the first body segment, and walk from fileIndex to its "after"
764
+ // value at the end
765
+ // If it doesn't match at that position, we increment, until we hit
766
+ // that final possible position, and give up.
767
+ // If it does match, then advance and try to rest.
768
+ // If any of them fail we keep walking forward.
769
+ // this is still a bit recursively painful, but it's more constrained
770
+ // than previous implementations, because we never test something that
771
+ // can't possibly be a valid matching condition.
772
+ const bs = bodySegments[bodyIndex];
773
+ if (!bs) {
774
+ // just make sure that there's no bad dots
775
+ for (let i = fileIndex; i < file.length; i++) {
776
+ sawTail = true;
777
+ const f = file[i];
778
+ if (f === '.' ||
779
+ f === '..' ||
780
+ (!this.options.dot && f.startsWith('.'))) {
781
+ return false;
782
+ }
783
+ }
784
+ return sawTail;
785
+ }
786
+ // have a non-globstar body section to test
787
+ const [body, after] = bs;
788
+ while (fileIndex <= after) {
789
+ const m = this.#matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
790
+ // if limit exceeded, no match. intentional false negative,
791
+ // acceptable break in correctness for security.
792
+ if (m && globStarDepth < this.maxGlobstarRecursion) {
793
+ // match! see if the rest match. if so, we're done!
794
+ const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
795
+ if (sub !== false) {
796
+ return sub;
797
+ }
798
+ }
799
+ const f = file[fileIndex];
800
+ if (f === '.' ||
801
+ f === '..' ||
802
+ (!this.options.dot && f.startsWith('.'))) {
803
+ return false;
804
+ }
805
+ fileIndex++;
806
+ }
807
+ // walked off. no point continuing
808
+ return partial || null;
809
+ }
810
+ #matchOne(file, pattern, partial, fileIndex, patternIndex) {
811
+ let fi;
812
+ let pi;
813
+ let pl;
814
+ let fl;
815
+ for (fi = fileIndex,
816
+ pi = patternIndex,
817
+ fl = file.length,
818
+ pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
654
819
  this.debug('matchOne loop');
655
- var p = pattern[pi];
656
- var f = file[fi];
820
+ let p = pattern[pi];
821
+ let f = file[fi];
657
822
  this.debug(pattern, p, f);
658
823
  // should be impossible.
659
824
  // some invalid regexp stuff in the set.
660
825
  /* c8 ignore start */
661
- if (p === false) {
826
+ if (p === false || p === GLOBSTAR) {
662
827
  return false;
663
828
  }
664
829
  /* c8 ignore stop */
665
- if (p === GLOBSTAR) {
666
- this.debug('GLOBSTAR', [pattern, p, f]);
667
- // "**"
668
- // a/**/b/**/c would match the following:
669
- // a/b/x/y/z/c
670
- // a/x/y/z/b/c
671
- // a/b/x/b/x/c
672
- // a/b/c
673
- // To do this, take the rest of the pattern after
674
- // the **, and see if it would match the file remainder.
675
- // If so, return success.
676
- // If not, the ** "swallows" a segment, and try again.
677
- // This is recursively awful.
678
- //
679
- // a/**/b/**/c matching a/b/x/y/z/c
680
- // - a matches a
681
- // - doublestar
682
- // - matchOne(b/x/y/z/c, b/**/c)
683
- // - b matches b
684
- // - doublestar
685
- // - matchOne(x/y/z/c, c) -> no
686
- // - matchOne(y/z/c, c) -> no
687
- // - matchOne(z/c, c) -> no
688
- // - matchOne(c, c) yes, hit
689
- var fr = fi;
690
- var pr = pi + 1;
691
- if (pr === pl) {
692
- this.debug('** at the end');
693
- // a ** at the end will just swallow the rest.
694
- // We have found a match.
695
- // however, it will not swallow /.x, unless
696
- // options.dot is set.
697
- // . and .. are *never* matched by **, for explosively
698
- // exponential reasons.
699
- for (; fi < fl; fi++) {
700
- if (file[fi] === '.' ||
701
- file[fi] === '..' ||
702
- (!options.dot && file[fi].charAt(0) === '.'))
703
- return false;
704
- }
705
- return true;
706
- }
707
- // ok, let's see if we can swallow whatever we can.
708
- while (fr < fl) {
709
- var swallowee = file[fr];
710
- this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
711
- // XXX remove this slice. Just pass the start index.
712
- if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
713
- this.debug('globstar found match!', fr, fl, swallowee);
714
- // found a match.
715
- return true;
716
- }
717
- else {
718
- // can't swallow "." or ".." ever.
719
- // can only swallow ".foo" when explicitly asked.
720
- if (swallowee === '.' ||
721
- swallowee === '..' ||
722
- (!options.dot && swallowee.charAt(0) === '.')) {
723
- this.debug('dot detected!', file, fr, pattern, pr);
724
- break;
725
- }
726
- // ** swallows a segment, and continue.
727
- this.debug('globstar swallow a segment, and continue');
728
- fr++;
729
- }
730
- }
731
- // no match was found.
732
- // However, in partial mode, we can't say this is necessarily over.
733
- /* c8 ignore start */
734
- if (partial) {
735
- // ran out of file
736
- this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
737
- if (fr === fl) {
738
- return true;
739
- }
740
- }
741
- /* c8 ignore stop */
742
- return false;
743
- }
744
830
  // something other than **
745
831
  // non-magic patterns just have to match exactly
746
832
  // patterns with magic have been turned into regexps.
@@ -2,7 +2,7 @@
2
2
  "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
3
3
  "name": "minimatch",
4
4
  "description": "a glob matcher in javascript",
5
- "version": "10.2.1",
5
+ "version": "10.2.4",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git@github.com:isaacs/minimatch"
@@ -39,13 +39,13 @@
39
39
  "typedoc": "typedoc --tsconfig .tshy/esm.json ./src/*.ts"
40
40
  },
41
41
  "engines": {
42
- "node": "20 || >=22"
42
+ "node": "18 || 20 || >=22"
43
43
  },
44
44
  "devDependencies": {
45
- "@types/node": "^24.0.0",
45
+ "@types/node": "^25.3.0",
46
46
  "mkdirp": "^3.0.1",
47
47
  "prettier": "^3.6.2",
48
- "tap": "^21.1.0",
48
+ "tap": "^21.6.2",
49
49
  "tshy": "^3.0.2",
50
50
  "typedoc": "^0.28.5"
51
51
  },
@@ -22,7 +22,11 @@ const isStream = (s) => !!s &&
22
22
  (s instanceof Minipass ||
23
23
  s instanceof node_stream_1.default ||
24
24
  (0, exports.isReadable)(s) ||
25
- (0, exports.isWritable)(s));
25
+ (0, exports.isWritable)(s))
26
+ /**
27
+ * Return true if the argument is a valid {@link Minipass.Readable}
28
+ */
29
+ ;
26
30
  exports.isStream = isStream;
27
31
  /**
28
32
  * Return true if the argument is a valid {@link Minipass.Readable}
@@ -32,7 +36,11 @@ const isReadable = (s) => !!s &&
32
36
  s instanceof node_events_1.EventEmitter &&
33
37
  typeof s.pipe === 'function' &&
34
38
  // node core Writable streams have a pipe() method, but it throws
35
- s.pipe !== node_stream_1.default.Writable.prototype.pipe;
39
+ s.pipe !== node_stream_1.default.Writable.prototype.pipe
40
+ /**
41
+ * Return true if the argument is a valid {@link Minipass.Writable}
42
+ */
43
+ ;
36
44
  exports.isReadable = isReadable;
37
45
  /**
38
46
  * Return true if the argument is a valid {@link Minipass.Writable}
@@ -129,7 +137,7 @@ class PipeProxyErrors extends Pipe {
129
137
  }
130
138
  constructor(src, dest, opts) {
131
139
  super(src, dest, opts);
132
- this.proxyErrors = er => dest.emit('error', er);
140
+ this.proxyErrors = (er) => this.dest.emit('error', er);
133
141
  src.on('error', this.proxyErrors);
134
142
  }
135
143
  }
@@ -939,6 +947,7 @@ class Minipass extends node_events_1.EventEmitter {
939
947
  [Symbol.asyncIterator]() {
940
948
  return this;
941
949
  },
950
+ [Symbol.asyncDispose]: async () => { },
942
951
  };
943
952
  }
944
953
  /**
@@ -976,6 +985,7 @@ class Minipass extends node_events_1.EventEmitter {
976
985
  [Symbol.iterator]() {
977
986
  return this;
978
987
  },
988
+ [Symbol.dispose]: () => { },
979
989
  };
980
990
  }
981
991
  /**
@@ -120,7 +120,7 @@ class PipeProxyErrors extends Pipe {
120
120
  }
121
121
  constructor(src, dest, opts) {
122
122
  super(src, dest, opts);
123
- this.proxyErrors = er => dest.emit('error', er);
123
+ this.proxyErrors = (er) => this.dest.emit('error', er);
124
124
  src.on('error', this.proxyErrors);
125
125
  }
126
126
  }
@@ -930,6 +930,7 @@ export class Minipass extends EventEmitter {
930
930
  [Symbol.asyncIterator]() {
931
931
  return this;
932
932
  },
933
+ [Symbol.asyncDispose]: async () => { },
933
934
  };
934
935
  }
935
936
  /**
@@ -967,6 +968,7 @@ export class Minipass extends EventEmitter {
967
968
  [Symbol.iterator]() {
968
969
  return this;
969
970
  },
971
+ [Symbol.dispose]: () => { },
970
972
  };
971
973
  }
972
974
  /**
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "minipass",
3
- "version": "7.1.2",
3
+ "version": "7.1.3",
4
4
  "description": "minimal implementation of a PassThrough stream",
5
5
  "main": "./dist/commonjs/index.js",
6
6
  "types": "./dist/commonjs/index.d.ts",
7
+ "module": "./dist/esm/index.js",
7
8
  "type": "module",
8
9
  "tshy": {
9
10
  "selfLink": false,
10
- "main": true,
11
+ "compiler": "tsgo",
11
12
  "exports": {
12
13
  "./package.json": "./package.json",
13
14
  ".": "./src/index.ts"
@@ -54,14 +55,14 @@
54
55
  },
55
56
  "devDependencies": {
56
57
  "@types/end-of-stream": "^1.4.2",
57
- "@types/node": "^20.1.2",
58
+ "@types/node": "^25.2.3",
58
59
  "end-of-stream": "^1.4.0",
59
60
  "node-abort-controller": "^3.1.1",
60
- "prettier": "^2.6.2",
61
- "tap": "^19.0.0",
61
+ "prettier": "^3.8.1",
62
+ "tap": "^21.6.1",
62
63
  "through2": "^2.0.3",
63
- "tshy": "^1.14.0",
64
- "typedoc": "^0.25.1"
64
+ "tshy": "^3.3.2",
65
+ "typedoc": "^0.28.17"
65
66
  },
66
67
  "repository": "https://github.com/isaacs/minipass",
67
68
  "keywords": [
@@ -69,14 +70,8 @@
69
70
  "stream"
70
71
  ],
71
72
  "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
72
- "license": "ISC",
73
+ "license": "BlueOak-1.0.0",
73
74
  "engines": {
74
75
  "node": ">=16 || 14 >=14.17"
75
- },
76
- "tap": {
77
- "typecheck": true,
78
- "include": [
79
- "test/*.ts"
80
- ]
81
76
  }
82
77
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "path-scurry",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "walk paths fast and efficiently",
5
5
  "author": "Isaac Z. Schlueter <i@izs.me> (https://blog.izs.me)",
6
6
  "main": "./dist/commonjs/index.js",
@@ -35,35 +35,19 @@
35
35
  "typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts",
36
36
  "bench": "bash ./scripts/bench.sh"
37
37
  },
38
- "prettier": {
39
- "experimentalTernaries": true,
40
- "semi": false,
41
- "printWidth": 75,
42
- "tabWidth": 2,
43
- "useTabs": false,
44
- "singleQuote": true,
45
- "jsxSingleQuote": false,
46
- "bracketSameLine": true,
47
- "arrowParens": "avoid",
48
- "endOfLine": "lf"
49
- },
50
38
  "devDependencies": {
51
- "@nodelib/fs.walk": "^2.0.0",
52
- "@types/node": "^20.14.10",
39
+ "@nodelib/fs.walk": "^3.0.1",
40
+ "@types/node": "^25.3.0",
53
41
  "mkdirp": "^3.0.0",
54
42
  "prettier": "^3.3.2",
55
- "rimraf": "^5.0.8",
56
- "tap": "^20.0.3",
43
+ "rimraf": "^6.1.3",
44
+ "tap": "^21.6.1",
57
45
  "ts-node": "^10.9.2",
58
- "tshy": "^2.0.1",
59
- "typedoc": "^0.26.3",
60
- "typescript": "^5.5.3"
61
- },
62
- "tap": {
63
- "typecheck": true
46
+ "tshy": "^3.3.2",
47
+ "typedoc": "^0.28.17"
64
48
  },
65
49
  "engines": {
66
- "node": "20 || >=22"
50
+ "node": "18 || 20 || >=22"
67
51
  },
68
52
  "funding": {
69
53
  "url": "https://github.com/sponsors/isaacs"