├── .eslintignore ├── .eslintrc ├── .github ├── CODEOWNERS └── workflows │ └── build.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .releaserc.json ├── .yarn ├── plugins │ └── @yarnpkg │ │ └── plugin-outdated.cjs └── releases │ └── yarn-4.0.2.cjs ├── .yarnrc.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── package.json ├── playwright.config.ts ├── src ├── Collection.ts ├── enhance.ts ├── index.ts └── utils.ts ├── test ├── dynamic-selectors.spec.ts ├── elements.spec.ts ├── frame-locators.spec.ts ├── methods.spec.ts ├── nested-collections.spec.ts ├── nth.spec.ts └── utility-methods.spec.ts ├── tsconfig.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["widen", "widen/typescript", "plugin:playwright/playwright-test"] 3 | } 4 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @mskelton @avo @joephela 2 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push] 3 | jobs: 4 | lint: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: mskelton/setup-yarn@v2 8 | - name: Lint 9 | run: yarn lint 10 | - name: Check styling 11 | run: yarn prettier --check . 12 | - name: Type check 13 | run: yarn tsc --noEmit 14 | test: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: mskelton/setup-yarn@v2 18 | - name: Install Playwright deps 19 | run: yarn playwright install chromium 20 | - name: Test 21 | run: yarn test 22 | - uses: actions/upload-artifact@v2 23 | if: ${{ always() }} 24 | with: 25 | name: test-artifacts 26 | path: test-results 27 | release: 28 | needs: [lint, test] 29 | runs-on: ubuntu-latest 30 | permissions: 31 | contents: write 32 | issues: write 33 | pull-requests: write 34 | steps: 35 | - uses: mskelton/setup-yarn@v2 36 | - name: Build 37 | run: yarn build 38 | - name: Release 39 | run: yarn semantic-release 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | node_modules/ 3 | dist/ 4 | test-results/ 5 | 6 | # Yarn 7 | .yarn/* 8 | !.yarn/releases 9 | !.yarn/plugins 10 | !.yarn/sdks 11 | !.yarn/versions 12 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Yarn auto-generated files 2 | .yarn/ 3 | .yarnrc.yml 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "proseWrap": "always" 5 | } 6 | -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@mskelton/semantic-release-config" 3 | } 4 | -------------------------------------------------------------------------------- /.yarn/plugins/@yarnpkg/plugin-outdated.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | //prettier-ignore 3 | module.exports = { 4 | name: "@yarnpkg/plugin-outdated", 5 | factory: function (require) { 6 | "use strict";var plugin=(()=>{var cr=Object.create;var Ht=Object.defineProperty;var hr=Object.getOwnPropertyDescriptor;var fr=Object.getOwnPropertyNames;var pr=Object.getPrototypeOf,dr=Object.prototype.hasOwnProperty;var gr=(s,t,e)=>t in s?Ht(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var q=(s=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(s,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):s)(function(s){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+s+'" is not supported')});var F=(s,t)=>()=>(t||s((t={exports:{}}).exports,t),t.exports),mr=(s,t)=>{for(var e in t)Ht(s,e,{get:t[e],enumerable:!0})},ve=(s,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of fr(t))!dr.call(s,i)&&i!==e&&Ht(s,i,{get:()=>t[i],enumerable:!(r=hr(t,i))||r.enumerable});return s};var Rt=(s,t,e)=>(e=s!=null?cr(pr(s)):{},ve(t||!s||!s.__esModule?Ht(e,"default",{value:s,enumerable:!0}):e,s)),yr=s=>ve(Ht({},"__esModule",{value:!0}),s);var re=(s,t,e)=>(gr(s,typeof t!="symbol"?t+"":t,e),e),ie=(s,t,e)=>{if(!t.has(s))throw TypeError("Cannot "+e)};var ot=(s,t,e)=>(ie(s,t,"read from private field"),e?e.call(s):t.get(s)),bt=(s,t,e)=>{if(t.has(s))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(s):t.set(s,e)},ne=(s,t,e,r)=>(ie(s,t,"write to private field"),r?r.call(s,e):t.set(s,e),e);var K=(s,t,e)=>(ie(s,t,"access private method"),e);var jt=F(rt=>{"use strict";rt.isInteger=s=>typeof s=="number"?Number.isInteger(s):typeof s=="string"&&s.trim()!==""?Number.isInteger(Number(s)):!1;rt.find=(s,t)=>s.nodes.find(e=>e.type===t);rt.exceedsLimit=(s,t,e=1,r)=>r===!1||!rt.isInteger(s)||!rt.isInteger(t)?!1:(Number(t)-Number(s))/Number(e)>=r;rt.escapeNode=(s,t=0,e)=>{let r=s.nodes[t];!r||(e&&r.type===e||r.type==="open"||r.type==="close")&&r.escaped!==!0&&(r.value="\\"+r.value,r.escaped=!0)};rt.encloseBrace=s=>s.type!=="brace"?!1:s.commas>>0+s.ranges>>0===0?(s.invalid=!0,!0):!1;rt.isInvalidBrace=s=>s.type!=="brace"?!1:s.invalid===!0||s.dollar?!0:s.commas>>0+s.ranges>>0===0||s.open!==!0||s.close!==!0?(s.invalid=!0,!0):!1;rt.isOpenOrClose=s=>s.type==="open"||s.type==="close"?!0:s.open===!0||s.close===!0;rt.reduce=s=>s.reduce((t,e)=>(e.type==="text"&&t.push(e.value),e.type==="range"&&(e.type="text"),t),[]);rt.flatten=(...s)=>{let t=[],e=r=>{for(let i=0;i{"use strict";var Te=jt();He.exports=(s,t={})=>{let e=(r,i={})=>{let n=t.escapeInvalid&&Te.isInvalidBrace(i),o=r.invalid===!0&&t.escapeInvalid===!0,a="";if(r.value)return(n||o)&&Te.isOpenOrClose(r)?"\\"+r.value:r.value;if(r.value)return r.value;if(r.nodes)for(let l of r.nodes)a+=e(l);return a};return e(s)}});var Le=F((Vi,Oe)=>{"use strict";Oe.exports=function(s){return typeof s=="number"?s-s===0:typeof s=="string"&&s.trim()!==""?Number.isFinite?Number.isFinite(+s):isFinite(+s):!1}});var We=F((Zi,Me)=>{"use strict";var ke=Le(),mt=(s,t,e)=>{if(ke(s)===!1)throw new TypeError("toRegexRange: expected the first argument to be a number");if(t===void 0||s===t)return String(s);if(ke(t)===!1)throw new TypeError("toRegexRange: expected the second argument to be a number.");let r={relaxZeros:!0,...e};typeof r.strictZeros=="boolean"&&(r.relaxZeros=r.strictZeros===!1);let i=String(r.relaxZeros),n=String(r.shorthand),o=String(r.capture),a=String(r.wrap),l=s+":"+t+"="+i+n+o+a;if(mt.cache.hasOwnProperty(l))return mt.cache[l].result;let d=Math.min(s,t),p=Math.max(s,t);if(Math.abs(d-p)===1){let m=s+"|"+t;return r.capture?`(${m})`:r.wrap===!1?m:`(?:${m})`}let g=Fe(s)||Fe(t),u={min:s,max:t,a:d,b:p},_=[],b=[];if(g&&(u.isPadded=g,u.maxLen=String(u.max).length),d<0){let m=p<0?Math.abs(p):1;b=Ne(m,Math.abs(d),u,r),d=u.a=0}return p>=0&&(_=Ne(d,p,u,r)),u.negatives=b,u.positives=_,u.result=Ar(b,_,r),r.capture===!0?u.result=`(${u.result})`:r.wrap!==!1&&_.length+b.length>1&&(u.result=`(?:${u.result})`),mt.cache[l]=u,u.result};function Ar(s,t,e){let r=oe(s,t,"-",!1,e)||[],i=oe(t,s,"",!1,e)||[],n=oe(s,t,"-?",!0,e)||[];return r.concat(n).concat(i).join("|")}function Rr(s,t){let e=1,r=1,i=Ie(s,e),n=new Set([t]);for(;s<=i&&i<=t;)n.add(i),e+=1,i=Ie(s,e);for(i=Ue(t+1,r)-1;s1&&a.count.pop(),a.count.push(p.count[0]),a.string=a.pattern+Pe(a.count),o=d+1;continue}e.isPadded&&(g=Sr(d,e,r)),p.string=g+p.pattern+Pe(p.count),n.push(p),o=d+1,a=p}return n}function oe(s,t,e,r,i){let n=[];for(let o of s){let{string:a}=o;!r&&!De(t,"string",a)&&n.push(e+a),r&&De(t,"string",a)&&n.push(e+a)}return n}function _r(s,t){let e=[];for(let r=0;rt?1:t>s?-1:0}function De(s,t,e){return s.some(r=>r[t]===e)}function Ie(s,t){return Number(String(s).slice(0,-t)+"9".repeat(t))}function Ue(s,t){return s-s%Math.pow(10,t)}function Pe(s){let[t=0,e=""]=s;return e||t>1?`{${t+(e?","+e:"")}}`:""}function Cr(s,t,e){return`[${s}${t-s===1?"":"-"}${t}]`}function Fe(s){return/^-?(0+)\d/.test(s)}function Sr(s,t,e){if(!t.isPadded)return s;let r=Math.abs(t.maxLen-String(s).length),i=e.relaxZeros!==!1;switch(r){case 0:return"";case 1:return i?"0?":"0";case 2:return i?"0{0,2}":"00";default:return i?`0{0,${r}}`:`0{${r}}`}}mt.cache={};mt.clearCache=()=>mt.cache={};Me.exports=mt});var ue=F((Yi,Xe)=>{"use strict";var wr=q("util"),ze=We(),Be=s=>s!==null&&typeof s=="object"&&!Array.isArray(s),$r=s=>t=>s===!0?Number(t):String(t),ae=s=>typeof s=="number"||typeof s=="string"&&s!=="",Ot=s=>Number.isInteger(+s),le=s=>{let t=`${s}`,e=-1;if(t[0]==="-"&&(t=t.slice(1)),t==="0")return!1;for(;t[++e]==="0";);return e>0},xr=(s,t,e)=>typeof s=="string"||typeof t=="string"?!0:e.stringify===!0,vr=(s,t,e)=>{if(t>0){let r=s[0]==="-"?"-":"";r&&(s=s.slice(1)),s=r+s.padStart(r?t-1:t,"0")}return e===!1?String(s):s},je=(s,t)=>{let e=s[0]==="-"?"-":"";for(e&&(s=s.slice(1),t--);s.length{s.negatives.sort((o,a)=>oa?1:0),s.positives.sort((o,a)=>oa?1:0);let e=t.capture?"":"?:",r="",i="",n;return s.positives.length&&(r=s.positives.join("|")),s.negatives.length&&(i=`-(${e}${s.negatives.join("|")})`),r&&i?n=`${r}|${i}`:n=r||i,t.wrap?`(${e}${n})`:n},Ge=(s,t,e,r)=>{if(e)return ze(s,t,{wrap:!1,...r});let i=String.fromCharCode(s);if(s===t)return i;let n=String.fromCharCode(t);return`[${i}-${n}]`},qe=(s,t,e)=>{if(Array.isArray(s)){let r=e.wrap===!0,i=e.capture?"":"?:";return r?`(${i}${s.join("|")})`:s.join("|")}return ze(s,t,e)},Ke=(...s)=>new RangeError("Invalid range arguments: "+wr.inspect(...s)),Qe=(s,t,e)=>{if(e.strictRanges===!0)throw Ke([s,t]);return[]},Hr=(s,t)=>{if(t.strictRanges===!0)throw new TypeError(`Expected step "${s}" to be a number`);return[]},Or=(s,t,e=1,r={})=>{let i=Number(s),n=Number(t);if(!Number.isInteger(i)||!Number.isInteger(n)){if(r.strictRanges===!0)throw Ke([s,t]);return[]}i===0&&(i=0),n===0&&(n=0);let o=i>n,a=String(s),l=String(t),d=String(e);e=Math.max(Math.abs(e),1);let p=le(a)||le(l)||le(d),g=p?Math.max(a.length,l.length,d.length):0,u=p===!1&&xr(s,t,r)===!1,_=r.transform||$r(u);if(r.toRegex&&e===1)return Ge(je(s,g),je(t,g),!0,r);let b={negatives:[],positives:[]},m=S=>b[S<0?"negatives":"positives"].push(Math.abs(S)),E=[],R=0;for(;o?i>=n:i<=n;)r.toRegex===!0&&e>1?m(i):E.push(vr(_(i,R),g,u)),i=o?i-e:i+e,R++;return r.toRegex===!0?e>1?Tr(b,r):qe(E,null,{wrap:!1,...r}):E},Lr=(s,t,e=1,r={})=>{if(!Ot(s)&&s.length>1||!Ot(t)&&t.length>1)return Qe(s,t,r);let i=r.transform||(u=>String.fromCharCode(u)),n=`${s}`.charCodeAt(0),o=`${t}`.charCodeAt(0),a=n>o,l=Math.min(n,o),d=Math.max(n,o);if(r.toRegex&&e===1)return Ge(l,d,!1,r);let p=[],g=0;for(;a?n>=o:n<=o;)p.push(i(n,g)),n=a?n-e:n+e,g++;return r.toRegex===!0?qe(p,null,{wrap:!1,options:r}):p},Gt=(s,t,e,r={})=>{if(t==null&&ae(s))return[s];if(!ae(s)||!ae(t))return Qe(s,t,r);if(typeof e=="function")return Gt(s,t,1,{transform:e});if(Be(e))return Gt(s,t,0,e);let i={...r};return i.capture===!0&&(i.wrap=!0),e=e||i.step||1,Ot(e)?Ot(s)&&Ot(t)?Or(s,t,e,i):Lr(s,t,Math.max(Math.abs(e),1),i):e!=null&&!Be(e)?Hr(e,i):Gt(s,t,1,e)};Xe.exports=Gt});var Ye=F((Ji,Ze)=>{"use strict";var kr=ue(),Ve=jt(),Nr=(s,t={})=>{let e=(r,i={})=>{let n=Ve.isInvalidBrace(i),o=r.invalid===!0&&t.escapeInvalid===!0,a=n===!0||o===!0,l=t.escapeInvalid===!0?"\\":"",d="";if(r.isOpen===!0||r.isClose===!0)return l+r.value;if(r.type==="open")return a?l+r.value:"(";if(r.type==="close")return a?l+r.value:")";if(r.type==="comma")return r.prev.type==="comma"?"":a?r.value:"|";if(r.value)return r.value;if(r.nodes&&r.ranges>0){let p=Ve.reduce(r.nodes),g=kr(...p,{...t,wrap:!1,toRegex:!0});if(g.length!==0)return p.length>1&&g.length>1?`(${g})`:g}if(r.nodes)for(let p of r.nodes)d+=e(p,r);return d};return e(s)};Ze.exports=Nr});var es=F((tn,ts)=>{"use strict";var Dr=ue(),Je=zt(),_t=jt(),yt=(s="",t="",e=!1)=>{let r=[];if(s=[].concat(s),t=[].concat(t),!t.length)return s;if(!s.length)return e?_t.flatten(t).map(i=>`{${i}}`):t;for(let i of s)if(Array.isArray(i))for(let n of i)r.push(yt(n,t,e));else for(let n of t)e===!0&&typeof n=="string"&&(n=`{${n}}`),r.push(Array.isArray(n)?yt(i,n,e):i+n);return _t.flatten(r)},Ir=(s,t={})=>{let e=t.rangeLimit===void 0?1e3:t.rangeLimit,r=(i,n={})=>{i.queue=[];let o=n,a=n.queue;for(;o.type!=="brace"&&o.type!=="root"&&o.parent;)o=o.parent,a=o.queue;if(i.invalid||i.dollar){a.push(yt(a.pop(),Je(i,t)));return}if(i.type==="brace"&&i.invalid!==!0&&i.nodes.length===2){a.push(yt(a.pop(),["{}"]));return}if(i.nodes&&i.ranges>0){let g=_t.reduce(i.nodes);if(_t.exceedsLimit(...g,t.step,e))throw new RangeError("expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.");let u=Dr(...g,t);u.length===0&&(u=Je(i,t)),a.push(yt(a.pop(),u)),i.nodes=[];return}let l=_t.encloseBrace(i),d=i.queue,p=i;for(;p.type!=="brace"&&p.type!=="root"&&p.parent;)p=p.parent,d=p.queue;for(let g=0;g{"use strict";ss.exports={MAX_LENGTH:1024*64,CHAR_0:"0",CHAR_9:"9",CHAR_UPPERCASE_A:"A",CHAR_LOWERCASE_A:"a",CHAR_UPPERCASE_Z:"Z",CHAR_LOWERCASE_Z:"z",CHAR_LEFT_PARENTHESES:"(",CHAR_RIGHT_PARENTHESES:")",CHAR_ASTERISK:"*",CHAR_AMPERSAND:"&",CHAR_AT:"@",CHAR_BACKSLASH:"\\",CHAR_BACKTICK:"`",CHAR_CARRIAGE_RETURN:"\r",CHAR_CIRCUMFLEX_ACCENT:"^",CHAR_COLON:":",CHAR_COMMA:",",CHAR_DOLLAR:"$",CHAR_DOT:".",CHAR_DOUBLE_QUOTE:'"',CHAR_EQUAL:"=",CHAR_EXCLAMATION_MARK:"!",CHAR_FORM_FEED:"\f",CHAR_FORWARD_SLASH:"/",CHAR_HASH:"#",CHAR_HYPHEN_MINUS:"-",CHAR_LEFT_ANGLE_BRACKET:"<",CHAR_LEFT_CURLY_BRACE:"{",CHAR_LEFT_SQUARE_BRACKET:"[",CHAR_LINE_FEED:` 7 | `,CHAR_NO_BREAK_SPACE:"\xA0",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:" ",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\uFEFF"}});var ls=F((sn,as)=>{"use strict";var Ur=zt(),{MAX_LENGTH:is,CHAR_BACKSLASH:ce,CHAR_BACKTICK:Pr,CHAR_COMMA:Fr,CHAR_DOT:Mr,CHAR_LEFT_PARENTHESES:Wr,CHAR_RIGHT_PARENTHESES:Br,CHAR_LEFT_CURLY_BRACE:jr,CHAR_RIGHT_CURLY_BRACE:zr,CHAR_LEFT_SQUARE_BRACKET:ns,CHAR_RIGHT_SQUARE_BRACKET:os,CHAR_DOUBLE_QUOTE:Gr,CHAR_SINGLE_QUOTE:qr,CHAR_NO_BREAK_SPACE:Kr,CHAR_ZERO_WIDTH_NOBREAK_SPACE:Qr}=rs(),Xr=(s,t={})=>{if(typeof s!="string")throw new TypeError("Expected a string");let e=t||{},r=typeof e.maxLength=="number"?Math.min(is,e.maxLength):is;if(s.length>r)throw new SyntaxError(`Input length (${s.length}), exceeds max characters (${r})`);let i={type:"root",input:s,nodes:[]},n=[i],o=i,a=i,l=0,d=s.length,p=0,g=0,u,_={},b=()=>s[p++],m=E=>{if(E.type==="text"&&a.type==="dot"&&(a.type="text"),a&&a.type==="text"&&E.type==="text"){a.value+=E.value;return}return o.nodes.push(E),E.parent=o,E.prev=a,a=E,E};for(m({type:"bos"});p0){if(o.ranges>0){o.ranges=0;let E=o.nodes.shift();o.nodes=[E,{type:"text",value:Ur(o)}]}m({type:"comma",value:u}),o.commas++;continue}if(u===Mr&&g>0&&o.commas===0){let E=o.nodes;if(g===0||E.length===0){m({type:"text",value:u});continue}if(a.type==="dot"){if(o.range=[],a.value+=u,a.type="range",o.nodes.length!==3&&o.nodes.length!==5){o.invalid=!0,o.ranges=0,a.type="text";continue}o.ranges++,o.args=[];continue}if(a.type==="range"){E.pop();let R=E[E.length-1];R.value+=a.value+u,a=R,o.ranges--;continue}m({type:"dot",value:u});continue}m({type:"text",value:u})}do if(o=n.pop(),o.type!=="root"){o.nodes.forEach(S=>{S.nodes||(S.type==="open"&&(S.isOpen=!0),S.type==="close"&&(S.isClose=!0),S.nodes||(S.type="text"),S.invalid=!0)});let E=n[n.length-1],R=E.nodes.indexOf(o);E.nodes.splice(R,1,...o.nodes)}while(n.length>0);return m({type:"eos"}),i};as.exports=Xr});var hs=F((rn,cs)=>{"use strict";var us=zt(),Vr=Ye(),Zr=es(),Yr=ls(),et=(s,t={})=>{let e=[];if(Array.isArray(s))for(let r of s){let i=et.create(r,t);Array.isArray(i)?e.push(...i):e.push(i)}else e=[].concat(et.create(s,t));return t&&t.expand===!0&&t.nodupes===!0&&(e=[...new Set(e)]),e};et.parse=(s,t={})=>Yr(s,t);et.stringify=(s,t={})=>us(typeof s=="string"?et.parse(s,t):s,t);et.compile=(s,t={})=>(typeof s=="string"&&(s=et.parse(s,t)),Vr(s,t));et.expand=(s,t={})=>{typeof s=="string"&&(s=et.parse(s,t));let e=Zr(s,t);return t.noempty===!0&&(e=e.filter(Boolean)),t.nodupes===!0&&(e=[...new Set(e)]),e};et.create=(s,t={})=>s===""||s.length<3?[s]:t.expand!==!0?et.compile(s,t):et.expand(s,t);cs.exports=et});var Lt=F((nn,ms)=>{"use strict";var Jr=q("path"),at="\\\\/",fs=`[^${at}]`,ct="\\.",ti="\\+",ei="\\?",qt="\\/",si="(?=.)",ps="[^/]",he=`(?:${qt}|$)`,ds=`(?:^|${qt})`,fe=`${ct}{1,2}${he}`,ri=`(?!${ct})`,ii=`(?!${ds}${fe})`,ni=`(?!${ct}{0,1}${he})`,oi=`(?!${fe})`,ai=`[^.${qt}]`,li=`${ps}*?`,gs={DOT_LITERAL:ct,PLUS_LITERAL:ti,QMARK_LITERAL:ei,SLASH_LITERAL:qt,ONE_CHAR:si,QMARK:ps,END_ANCHOR:he,DOTS_SLASH:fe,NO_DOT:ri,NO_DOTS:ii,NO_DOT_SLASH:ni,NO_DOTS_SLASH:oi,QMARK_NO_DOT:ai,STAR:li,START_ANCHOR:ds},ui={...gs,SLASH_LITERAL:`[${at}]`,QMARK:fs,STAR:`${fs}*?`,DOTS_SLASH:`${ct}{1,2}(?:[${at}]|$)`,NO_DOT:`(?!${ct})`,NO_DOTS:`(?!(?:^|[${at}])${ct}{1,2}(?:[${at}]|$))`,NO_DOT_SLASH:`(?!${ct}{0,1}(?:[${at}]|$))`,NO_DOTS_SLASH:`(?!${ct}{1,2}(?:[${at}]|$))`,QMARK_NO_DOT:`[^.${at}]`,START_ANCHOR:`(?:^|[${at}])`,END_ANCHOR:`(?:[${at}]|$)`},ci={alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};ms.exports={MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:ci,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,SEP:Jr.sep,extglobChars(s){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${s.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(s){return s===!0?ui:gs}}});var kt=F(Y=>{"use strict";var hi=q("path"),fi=process.platform==="win32",{REGEX_BACKSLASH:pi,REGEX_REMOVE_BACKSLASH:di,REGEX_SPECIAL_CHARS:gi,REGEX_SPECIAL_CHARS_GLOBAL:mi}=Lt();Y.isObject=s=>s!==null&&typeof s=="object"&&!Array.isArray(s);Y.hasRegexChars=s=>gi.test(s);Y.isRegexChar=s=>s.length===1&&Y.hasRegexChars(s);Y.escapeRegex=s=>s.replace(mi,"\\$1");Y.toPosixSlashes=s=>s.replace(pi,"/");Y.removeBackslashes=s=>s.replace(di,t=>t==="\\"?"":t);Y.supportsLookbehinds=()=>{let s=process.version.slice(1).split(".").map(Number);return s.length===3&&s[0]>=9||s[0]===8&&s[1]>=10};Y.isWindows=s=>s&&typeof s.windows=="boolean"?s.windows:fi===!0||hi.sep==="\\";Y.escapeLast=(s,t,e)=>{let r=s.lastIndexOf(t,e);return r===-1?s:s[r-1]==="\\"?Y.escapeLast(s,t,r-1):`${s.slice(0,r)}\\${s.slice(r)}`};Y.removePrefix=(s,t={})=>{let e=s;return e.startsWith("./")&&(e=e.slice(2),t.prefix="./"),e};Y.wrapOutput=(s,t={},e={})=>{let r=e.contains?"":"^",i=e.contains?"":"$",n=`${r}(?:${s})${i}`;return t.negated===!0&&(n=`(?:^(?!${n}).*$)`),n}});var Ss=F((an,Cs)=>{"use strict";var ys=kt(),{CHAR_ASTERISK:pe,CHAR_AT:yi,CHAR_BACKWARD_SLASH:Nt,CHAR_COMMA:Ai,CHAR_DOT:de,CHAR_EXCLAMATION_MARK:ge,CHAR_FORWARD_SLASH:Es,CHAR_LEFT_CURLY_BRACE:me,CHAR_LEFT_PARENTHESES:ye,CHAR_LEFT_SQUARE_BRACKET:Ri,CHAR_PLUS:bi,CHAR_QUESTION_MARK:As,CHAR_RIGHT_CURLY_BRACE:_i,CHAR_RIGHT_PARENTHESES:Rs,CHAR_RIGHT_SQUARE_BRACKET:Ei}=Lt(),bs=s=>s===Es||s===Nt,_s=s=>{s.isPrefix!==!0&&(s.depth=s.isGlobstar?1/0:1)},Ci=(s,t)=>{let e=t||{},r=s.length-1,i=e.parts===!0||e.scanToEnd===!0,n=[],o=[],a=[],l=s,d=-1,p=0,g=0,u=!1,_=!1,b=!1,m=!1,E=!1,R=!1,S=!1,x=!1,L=!1,O=!1,X=0,D,C,v={value:"",depth:0,isGlob:!1},B=()=>d>=r,f=()=>l.charCodeAt(d+1),I=()=>(D=C,l.charCodeAt(++d));for(;d0&&(ht=l.slice(0,p),l=l.slice(p),g-=p),k&&b===!0&&g>0?(k=l.slice(0,g),c=l.slice(g)):b===!0?(k="",c=l):k=l,k&&k!==""&&k!=="/"&&k!==l&&bs(k.charCodeAt(k.length-1))&&(k=k.slice(0,-1)),e.unescape===!0&&(c&&(c=ys.removeBackslashes(c)),k&&S===!0&&(k=ys.removeBackslashes(k)));let h={prefix:ht,input:s,start:p,base:k,glob:c,isBrace:u,isBracket:_,isGlob:b,isExtglob:m,isGlobstar:E,negated:x,negatedExtglob:L};if(e.tokens===!0&&(h.maxDepth=0,bs(C)||o.push(v),h.tokens=o),e.parts===!0||e.tokens===!0){let V;for(let T=0;T{"use strict";var Kt=Lt(),st=kt(),{MAX_LENGTH:Qt,POSIX_REGEX_SOURCE:Si,REGEX_NON_SPECIAL_CHARS:wi,REGEX_SPECIAL_CHARS_BACKREF:$i,REPLACEMENTS:ws}=Kt,xi=(s,t)=>{if(typeof t.expandRange=="function")return t.expandRange(...s,t);s.sort();let e=`[${s.join("-")}]`;try{new RegExp(e)}catch{return s.map(i=>st.escapeRegex(i)).join("..")}return e},Et=(s,t)=>`Missing ${s}: "${t}" - use "\\\\${t}" to match literal characters`,Ae=(s,t)=>{if(typeof s!="string")throw new TypeError("Expected a string");s=ws[s]||s;let e={...t},r=typeof e.maxLength=="number"?Math.min(Qt,e.maxLength):Qt,i=s.length;if(i>r)throw new SyntaxError(`Input length: ${i}, exceeds maximum allowed length: ${r}`);let n={type:"bos",value:"",output:e.prepend||""},o=[n],a=e.capture?"":"?:",l=st.isWindows(t),d=Kt.globChars(l),p=Kt.extglobChars(d),{DOT_LITERAL:g,PLUS_LITERAL:u,SLASH_LITERAL:_,ONE_CHAR:b,DOTS_SLASH:m,NO_DOT:E,NO_DOT_SLASH:R,NO_DOTS_SLASH:S,QMARK:x,QMARK_NO_DOT:L,STAR:O,START_ANCHOR:X}=d,D=A=>`(${a}(?:(?!${X}${A.dot?m:g}).)*?)`,C=e.dot?"":E,v=e.dot?x:L,B=e.bash===!0?D(e):O;e.capture&&(B=`(${B})`),typeof e.noext=="boolean"&&(e.noextglob=e.noext);let f={input:s,index:-1,start:0,dot:e.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:o};s=st.removePrefix(s,f),i=s.length;let I=[],k=[],ht=[],c=n,h,V=()=>f.index===i-1,T=f.peek=(A=1)=>s[f.index+A],it=f.advance=()=>s[++f.index]||"",nt=()=>s.slice(f.index+1),tt=(A="",N=0)=>{f.consumed+=A,f.index+=N},Ft=A=>{f.output+=A.output!=null?A.output:A.value,tt(A.value)},lr=()=>{let A=1;for(;T()==="!"&&(T(2)!=="("||T(3)==="?");)it(),f.start++,A++;return A%2===0?!1:(f.negated=!0,f.start++,!0)},Mt=A=>{f[A]++,ht.push(A)},gt=A=>{f[A]--,ht.pop()},$=A=>{if(c.type==="globstar"){let N=f.braces>0&&(A.type==="comma"||A.type==="brace"),y=A.extglob===!0||I.length&&(A.type==="pipe"||A.type==="paren");A.type!=="slash"&&A.type!=="paren"&&!N&&!y&&(f.output=f.output.slice(0,-c.output.length),c.type="star",c.value="*",c.output=B,f.output+=c.output)}if(I.length&&A.type!=="paren"&&(I[I.length-1].inner+=A.value),(A.value||A.output)&&Ft(A),c&&c.type==="text"&&A.type==="text"){c.value+=A.value,c.output=(c.output||"")+A.value;return}A.prev=c,o.push(A),c=A},Wt=(A,N)=>{let y={...p[N],conditions:1,inner:""};y.prev=c,y.parens=f.parens,y.output=f.output;let w=(e.capture?"(":"")+y.open;Mt("parens"),$({type:A,value:N,output:f.output?"":b}),$({type:"paren",extglob:!0,value:it(),output:w}),I.push(y)},ur=A=>{let N=A.close+(e.capture?")":""),y;if(A.type==="negate"){let w=B;if(A.inner&&A.inner.length>1&&A.inner.includes("/")&&(w=D(e)),(w!==B||V()||/^\)+$/.test(nt()))&&(N=A.close=`)$))${w}`),A.inner.includes("*")&&(y=nt())&&/^\.[^\\/.]+$/.test(y)){let P=Ae(y,{...t,fastpaths:!1}).output;N=A.close=`)${P})${w})`}A.prev.type==="bos"&&(f.negatedExtglob=!0)}$({type:"paren",extglob:!0,value:h,output:N}),gt("parens")};if(e.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(s)){let A=!1,N=s.replace($i,(y,w,P,Z,z,se)=>Z==="\\"?(A=!0,y):Z==="?"?w?w+Z+(z?x.repeat(z.length):""):se===0?v+(z?x.repeat(z.length):""):x.repeat(P.length):Z==="."?g.repeat(P.length):Z==="*"?w?w+Z+(z?B:""):B:w?y:`\\${y}`);return A===!0&&(e.unescape===!0?N=N.replace(/\\/g,""):N=N.replace(/\\+/g,y=>y.length%2===0?"\\\\":y?"\\":"")),N===s&&e.contains===!0?(f.output=s,f):(f.output=st.wrapOutput(N,f,t),f)}for(;!V();){if(h=it(),h==="\0")continue;if(h==="\\"){let y=T();if(y==="/"&&e.bash!==!0||y==="."||y===";")continue;if(!y){h+="\\",$({type:"text",value:h});continue}let w=/^\\+/.exec(nt()),P=0;if(w&&w[0].length>2&&(P=w[0].length,f.index+=P,P%2!==0&&(h+="\\")),e.unescape===!0?h=it():h+=it(),f.brackets===0){$({type:"text",value:h});continue}}if(f.brackets>0&&(h!=="]"||c.value==="["||c.value==="[^")){if(e.posix!==!1&&h===":"){let y=c.value.slice(1);if(y.includes("[")&&(c.posix=!0,y.includes(":"))){let w=c.value.lastIndexOf("["),P=c.value.slice(0,w),Z=c.value.slice(w+2),z=Si[Z];if(z){c.value=P+z,f.backtrack=!0,it(),!n.output&&o.indexOf(c)===1&&(n.output=b);continue}}}(h==="["&&T()!==":"||h==="-"&&T()==="]")&&(h=`\\${h}`),h==="]"&&(c.value==="["||c.value==="[^")&&(h=`\\${h}`),e.posix===!0&&h==="!"&&c.value==="["&&(h="^"),c.value+=h,Ft({value:h});continue}if(f.quotes===1&&h!=='"'){h=st.escapeRegex(h),c.value+=h,Ft({value:h});continue}if(h==='"'){f.quotes=f.quotes===1?0:1,e.keepQuotes===!0&&$({type:"text",value:h});continue}if(h==="("){Mt("parens"),$({type:"paren",value:h});continue}if(h===")"){if(f.parens===0&&e.strictBrackets===!0)throw new SyntaxError(Et("opening","("));let y=I[I.length-1];if(y&&f.parens===y.parens+1){ur(I.pop());continue}$({type:"paren",value:h,output:f.parens?")":"\\)"}),gt("parens");continue}if(h==="["){if(e.nobracket===!0||!nt().includes("]")){if(e.nobracket!==!0&&e.strictBrackets===!0)throw new SyntaxError(Et("closing","]"));h=`\\${h}`}else Mt("brackets");$({type:"bracket",value:h});continue}if(h==="]"){if(e.nobracket===!0||c&&c.type==="bracket"&&c.value.length===1){$({type:"text",value:h,output:`\\${h}`});continue}if(f.brackets===0){if(e.strictBrackets===!0)throw new SyntaxError(Et("opening","["));$({type:"text",value:h,output:`\\${h}`});continue}gt("brackets");let y=c.value.slice(1);if(c.posix!==!0&&y[0]==="^"&&!y.includes("/")&&(h=`/${h}`),c.value+=h,Ft({value:h}),e.literalBrackets===!1||st.hasRegexChars(y))continue;let w=st.escapeRegex(c.value);if(f.output=f.output.slice(0,-c.value.length),e.literalBrackets===!0){f.output+=w,c.value=w;continue}c.value=`(${a}${w}|${c.value})`,f.output+=c.value;continue}if(h==="{"&&e.nobrace!==!0){Mt("braces");let y={type:"brace",value:h,output:"(",outputIndex:f.output.length,tokensIndex:f.tokens.length};k.push(y),$(y);continue}if(h==="}"){let y=k[k.length-1];if(e.nobrace===!0||!y){$({type:"text",value:h,output:h});continue}let w=")";if(y.dots===!0){let P=o.slice(),Z=[];for(let z=P.length-1;z>=0&&(o.pop(),P[z].type!=="brace");z--)P[z].type!=="dots"&&Z.unshift(P[z].value);w=xi(Z,e),f.backtrack=!0}if(y.comma!==!0&&y.dots!==!0){let P=f.output.slice(0,y.outputIndex),Z=f.tokens.slice(y.tokensIndex);y.value=y.output="\\{",h=w="\\}",f.output=P;for(let z of Z)f.output+=z.output||z.value}$({type:"brace",value:h,output:w}),gt("braces"),k.pop();continue}if(h==="|"){I.length>0&&I[I.length-1].conditions++,$({type:"text",value:h});continue}if(h===","){let y=h,w=k[k.length-1];w&&ht[ht.length-1]==="braces"&&(w.comma=!0,y="|"),$({type:"comma",value:h,output:y});continue}if(h==="/"){if(c.type==="dot"&&f.index===f.start+1){f.start=f.index+1,f.consumed="",f.output="",o.pop(),c=n;continue}$({type:"slash",value:h,output:_});continue}if(h==="."){if(f.braces>0&&c.type==="dot"){c.value==="."&&(c.output=g);let y=k[k.length-1];c.type="dots",c.output+=h,c.value+=h,y.dots=!0;continue}if(f.braces+f.parens===0&&c.type!=="bos"&&c.type!=="slash"){$({type:"text",value:h,output:g});continue}$({type:"dot",value:h,output:g});continue}if(h==="?"){if(!(c&&c.value==="(")&&e.noextglob!==!0&&T()==="("&&T(2)!=="?"){Wt("qmark",h);continue}if(c&&c.type==="paren"){let w=T(),P=h;if(w==="<"&&!st.supportsLookbehinds())throw new Error("Node.js v10 or higher is required for regex lookbehinds");(c.value==="("&&!/[!=<:]/.test(w)||w==="<"&&!/<([!=]|\w+>)/.test(nt()))&&(P=`\\${h}`),$({type:"text",value:h,output:P});continue}if(e.dot!==!0&&(c.type==="slash"||c.type==="bos")){$({type:"qmark",value:h,output:L});continue}$({type:"qmark",value:h,output:x});continue}if(h==="!"){if(e.noextglob!==!0&&T()==="("&&(T(2)!=="?"||!/[!=<:]/.test(T(3)))){Wt("negate",h);continue}if(e.nonegate!==!0&&f.index===0){lr();continue}}if(h==="+"){if(e.noextglob!==!0&&T()==="("&&T(2)!=="?"){Wt("plus",h);continue}if(c&&c.value==="("||e.regex===!1){$({type:"plus",value:h,output:u});continue}if(c&&(c.type==="bracket"||c.type==="paren"||c.type==="brace")||f.parens>0){$({type:"plus",value:h});continue}$({type:"plus",value:u});continue}if(h==="@"){if(e.noextglob!==!0&&T()==="("&&T(2)!=="?"){$({type:"at",extglob:!0,value:h,output:""});continue}$({type:"text",value:h});continue}if(h!=="*"){(h==="$"||h==="^")&&(h=`\\${h}`);let y=wi.exec(nt());y&&(h+=y[0],f.index+=y[0].length),$({type:"text",value:h});continue}if(c&&(c.type==="globstar"||c.star===!0)){c.type="star",c.star=!0,c.value+=h,c.output=B,f.backtrack=!0,f.globstar=!0,tt(h);continue}let A=nt();if(e.noextglob!==!0&&/^\([^?]/.test(A)){Wt("star",h);continue}if(c.type==="star"){if(e.noglobstar===!0){tt(h);continue}let y=c.prev,w=y.prev,P=y.type==="slash"||y.type==="bos",Z=w&&(w.type==="star"||w.type==="globstar");if(e.bash===!0&&(!P||A[0]&&A[0]!=="/")){$({type:"star",value:h,output:""});continue}let z=f.braces>0&&(y.type==="comma"||y.type==="brace"),se=I.length&&(y.type==="pipe"||y.type==="paren");if(!P&&y.type!=="paren"&&!z&&!se){$({type:"star",value:h,output:""});continue}for(;A.slice(0,3)==="/**";){let Bt=s[f.index+4];if(Bt&&Bt!=="/")break;A=A.slice(3),tt("/**",3)}if(y.type==="bos"&&V()){c.type="globstar",c.value+=h,c.output=D(e),f.output=c.output,f.globstar=!0,tt(h);continue}if(y.type==="slash"&&y.prev.type!=="bos"&&!Z&&V()){f.output=f.output.slice(0,-(y.output+c.output).length),y.output=`(?:${y.output}`,c.type="globstar",c.output=D(e)+(e.strictSlashes?")":"|$)"),c.value+=h,f.globstar=!0,f.output+=y.output+c.output,tt(h);continue}if(y.type==="slash"&&y.prev.type!=="bos"&&A[0]==="/"){let Bt=A[1]!==void 0?"|$":"";f.output=f.output.slice(0,-(y.output+c.output).length),y.output=`(?:${y.output}`,c.type="globstar",c.output=`${D(e)}${_}|${_}${Bt})`,c.value+=h,f.output+=y.output+c.output,f.globstar=!0,tt(h+it()),$({type:"slash",value:"/",output:""});continue}if(y.type==="bos"&&A[0]==="/"){c.type="globstar",c.value+=h,c.output=`(?:^|${_}|${D(e)}${_})`,f.output=c.output,f.globstar=!0,tt(h+it()),$({type:"slash",value:"/",output:""});continue}f.output=f.output.slice(0,-c.output.length),c.type="globstar",c.output=D(e),c.value+=h,f.output+=c.output,f.globstar=!0,tt(h);continue}let N={type:"star",value:h,output:B};if(e.bash===!0){N.output=".*?",(c.type==="bos"||c.type==="slash")&&(N.output=C+N.output),$(N);continue}if(c&&(c.type==="bracket"||c.type==="paren")&&e.regex===!0){N.output=h,$(N);continue}(f.index===f.start||c.type==="slash"||c.type==="dot")&&(c.type==="dot"?(f.output+=R,c.output+=R):e.dot===!0?(f.output+=S,c.output+=S):(f.output+=C,c.output+=C),T()!=="*"&&(f.output+=b,c.output+=b)),$(N)}for(;f.brackets>0;){if(e.strictBrackets===!0)throw new SyntaxError(Et("closing","]"));f.output=st.escapeLast(f.output,"["),gt("brackets")}for(;f.parens>0;){if(e.strictBrackets===!0)throw new SyntaxError(Et("closing",")"));f.output=st.escapeLast(f.output,"("),gt("parens")}for(;f.braces>0;){if(e.strictBrackets===!0)throw new SyntaxError(Et("closing","}"));f.output=st.escapeLast(f.output,"{"),gt("braces")}if(e.strictSlashes!==!0&&(c.type==="star"||c.type==="bracket")&&$({type:"maybe_slash",value:"",output:`${_}?`}),f.backtrack===!0){f.output="";for(let A of f.tokens)f.output+=A.output!=null?A.output:A.value,A.suffix&&(f.output+=A.suffix)}return f};Ae.fastpaths=(s,t)=>{let e={...t},r=typeof e.maxLength=="number"?Math.min(Qt,e.maxLength):Qt,i=s.length;if(i>r)throw new SyntaxError(`Input length: ${i}, exceeds maximum allowed length: ${r}`);s=ws[s]||s;let n=st.isWindows(t),{DOT_LITERAL:o,SLASH_LITERAL:a,ONE_CHAR:l,DOTS_SLASH:d,NO_DOT:p,NO_DOTS:g,NO_DOTS_SLASH:u,STAR:_,START_ANCHOR:b}=Kt.globChars(n),m=e.dot?g:p,E=e.dot?u:p,R=e.capture?"":"?:",S={negated:!1,prefix:""},x=e.bash===!0?".*?":_;e.capture&&(x=`(${x})`);let L=C=>C.noglobstar===!0?x:`(${R}(?:(?!${b}${C.dot?d:o}).)*?)`,O=C=>{switch(C){case"*":return`${m}${l}${x}`;case".*":return`${o}${l}${x}`;case"*.*":return`${m}${x}${o}${l}${x}`;case"*/*":return`${m}${x}${a}${l}${E}${x}`;case"**":return m+L(e);case"**/*":return`(?:${m}${L(e)}${a})?${E}${l}${x}`;case"**/*.*":return`(?:${m}${L(e)}${a})?${E}${x}${o}${l}${x}`;case"**/.*":return`(?:${m}${L(e)}${a})?${o}${l}${x}`;default:{let v=/^(.*?)\.(\w+)$/.exec(C);if(!v)return;let B=O(v[1]);return B?B+o+v[2]:void 0}}},X=st.removePrefix(s,S),D=O(X);return D&&e.strictSlashes!==!0&&(D+=`${a}?`),D};$s.exports=Ae});var Ts=F((un,vs)=>{"use strict";var vi=q("path"),Ti=Ss(),Re=xs(),be=kt(),Hi=Lt(),Oi=s=>s&&typeof s=="object"&&!Array.isArray(s),M=(s,t,e=!1)=>{if(Array.isArray(s)){let p=s.map(u=>M(u,t,e));return u=>{for(let _ of p){let b=_(u);if(b)return b}return!1}}let r=Oi(s)&&s.tokens&&s.input;if(s===""||typeof s!="string"&&!r)throw new TypeError("Expected pattern to be a non-empty string");let i=t||{},n=be.isWindows(t),o=r?M.compileRe(s,t):M.makeRe(s,t,!1,!0),a=o.state;delete o.state;let l=()=>!1;if(i.ignore){let p={...t,ignore:null,onMatch:null,onResult:null};l=M(i.ignore,p,e)}let d=(p,g=!1)=>{let{isMatch:u,match:_,output:b}=M.test(p,o,t,{glob:s,posix:n}),m={glob:s,state:a,regex:o,posix:n,input:p,output:b,match:_,isMatch:u};return typeof i.onResult=="function"&&i.onResult(m),u===!1?(m.isMatch=!1,g?m:!1):l(p)?(typeof i.onIgnore=="function"&&i.onIgnore(m),m.isMatch=!1,g?m:!1):(typeof i.onMatch=="function"&&i.onMatch(m),g?m:!0)};return e&&(d.state=a),d};M.test=(s,t,e,{glob:r,posix:i}={})=>{if(typeof s!="string")throw new TypeError("Expected input to be a string");if(s==="")return{isMatch:!1,output:""};let n=e||{},o=n.format||(i?be.toPosixSlashes:null),a=s===r,l=a&&o?o(s):s;return a===!1&&(l=o?o(s):s,a=l===r),(a===!1||n.capture===!0)&&(n.matchBase===!0||n.basename===!0?a=M.matchBase(s,t,e,i):a=t.exec(l)),{isMatch:Boolean(a),match:a,output:l}};M.matchBase=(s,t,e,r=be.isWindows(e))=>(t instanceof RegExp?t:M.makeRe(t,e)).test(vi.basename(s));M.isMatch=(s,t,e)=>M(t,e)(s);M.parse=(s,t)=>Array.isArray(s)?s.map(e=>M.parse(e,t)):Re(s,{...t,fastpaths:!1});M.scan=(s,t)=>Ti(s,t);M.compileRe=(s,t,e=!1,r=!1)=>{if(e===!0)return s.output;let i=t||{},n=i.contains?"":"^",o=i.contains?"":"$",a=`${n}(?:${s.output})${o}`;s&&s.negated===!0&&(a=`^(?!${a}).*$`);let l=M.toRegex(a,t);return r===!0&&(l.state=s),l};M.makeRe=(s,t={},e=!1,r=!1)=>{if(!s||typeof s!="string")throw new TypeError("Expected a non-empty string");let i={negated:!1,fastpaths:!0};return t.fastpaths!==!1&&(s[0]==="."||s[0]==="*")&&(i.output=Re.fastpaths(s,t)),i.output||(i=Re(s,t)),M.compileRe(i,t,e,r)};M.toRegex=(s,t)=>{try{let e=t||{};return new RegExp(s,e.flags||(e.nocase?"i":""))}catch(e){if(t&&t.debug===!0)throw e;return/$^/}};M.constants=Hi;vs.exports=M});var Os=F((cn,Hs)=>{"use strict";Hs.exports=Ts()});var Is=F((hn,Ds)=>{"use strict";var ks=q("util"),Ns=hs(),lt=Os(),_e=kt(),Ls=s=>s===""||s==="./",U=(s,t,e)=>{t=[].concat(t),s=[].concat(s);let r=new Set,i=new Set,n=new Set,o=0,a=p=>{n.add(p.output),e&&e.onResult&&e.onResult(p)};for(let p=0;p!r.has(p));if(e&&d.length===0){if(e.failglob===!0)throw new Error(`No matches found for "${t.join(", ")}"`);if(e.nonull===!0||e.nullglob===!0)return e.unescape?t.map(p=>p.replace(/\\/g,"")):t}return d};U.match=U;U.matcher=(s,t)=>lt(s,t);U.isMatch=(s,t,e)=>lt(t,e)(s);U.any=U.isMatch;U.not=(s,t,e={})=>{t=[].concat(t).map(String);let r=new Set,i=[],n=a=>{e.onResult&&e.onResult(a),i.push(a.output)},o=new Set(U(s,t,{...e,onResult:n}));for(let a of i)o.has(a)||r.add(a);return[...r]};U.contains=(s,t,e)=>{if(typeof s!="string")throw new TypeError(`Expected a string: "${ks.inspect(s)}"`);if(Array.isArray(t))return t.some(r=>U.contains(s,r,e));if(typeof t=="string"){if(Ls(s)||Ls(t))return!1;if(s.includes(t)||s.startsWith("./")&&s.slice(2).includes(t))return!0}return U.isMatch(s,t,{...e,contains:!0})};U.matchKeys=(s,t,e)=>{if(!_e.isObject(s))throw new TypeError("Expected the first argument to be an object");let r=U(Object.keys(s),t,e),i={};for(let n of r)i[n]=s[n];return i};U.some=(s,t,e)=>{let r=[].concat(s);for(let i of[].concat(t)){let n=lt(String(i),e);if(r.some(o=>n(o)))return!0}return!1};U.every=(s,t,e)=>{let r=[].concat(s);for(let i of[].concat(t)){let n=lt(String(i),e);if(!r.every(o=>n(o)))return!1}return!0};U.all=(s,t,e)=>{if(typeof s!="string")throw new TypeError(`Expected a string: "${ks.inspect(s)}"`);return[].concat(t).every(r=>lt(r,e)(s))};U.capture=(s,t,e)=>{let r=_e.isWindows(e),n=lt.makeRe(String(s),{...e,capture:!0}).exec(r?_e.toPosixSlashes(t):t);if(n)return n.slice(1).map(o=>o===void 0?"":o)};U.makeRe=(...s)=>lt.makeRe(...s);U.scan=(...s)=>lt.scan(...s);U.parse=(s,t)=>{let e=[];for(let r of[].concat(s||[]))for(let i of Ns(String(r),t))e.push(lt.parse(i,t));return e};U.braces=(s,t)=>{if(typeof s!="string")throw new TypeError("Expected a string");return t&&t.nobrace===!0||!/\{.*\}/.test(s)?[s]:Ns(s,t)};U.braceExpand=(s,t)=>{if(typeof s!="string")throw new TypeError("Expected a string");return U.braces(s,{...t,expand:!0})};Ds.exports=U});var Ws=F(Zt=>{"use strict";Object.defineProperty(Zt,"__esModule",{value:!0});Zt.LRUCache=void 0;var Ct=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date,Ps=new Set,Ee=typeof process=="object"&&!!process?process:{},Fs=(s,t,e,r)=>{typeof Ee.emitWarning=="function"?Ee.emitWarning(s,t,e,r):console.error(`[${e}] ${t}: ${s}`)},Vt=globalThis.AbortController,Us=globalThis.AbortSignal;if(typeof Vt>"u"){Us=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(r,i){this._onabort.push(i)}},Vt=class{constructor(){t()}signal=new Us;abort(r){if(!this.signal.aborted){this.signal.reason=r,this.signal.aborted=!0;for(let i of this.signal._onabort)i(r);this.signal.onabort?.(r)}}};let s=Ee.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",t=()=>{!s||(s=!1,Fs("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",t))}}var Li=s=>!Ps.has(s),dn=Symbol("type"),ft=s=>s&&s===Math.floor(s)&&s>0&&isFinite(s),Ms=s=>ft(s)?s<=Math.pow(2,8)?Uint8Array:s<=Math.pow(2,16)?Uint16Array:s<=Math.pow(2,32)?Uint32Array:s<=Number.MAX_SAFE_INTEGER?wt:null:null,wt=class extends Array{constructor(t){super(t),this.fill(0)}},$t,St=class{heap;length;static create(t){let e=Ms(t);if(!e)return[];ne(St,$t,!0);let r=new St(t,e);return ne(St,$t,!1),r}constructor(t,e){if(!ot(St,$t))throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},Xt=St;$t=new WeakMap,bt(Xt,$t,!1);var Dt=class{#d;#c;#g;#m;#T;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#i;#y;#r;#s;#t;#l;#h;#a;#n;#A;#o;#R;#b;#f;#_;#w;#u;static unsafeExposeInternals(t){return{starts:t.#b,ttls:t.#f,sizes:t.#R,keyMap:t.#r,keyList:t.#s,valList:t.#t,next:t.#l,prev:t.#h,get head(){return t.#a},get tail(){return t.#n},free:t.#A,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,r,i,n)=>t.#L(e,r,i,n),moveToTail:e=>t.#v(e),indexes:e=>t.#E(e),rindexes:e=>t.#C(e),isStale:e=>t.#p(e)}}get max(){return this.#d}get maxSize(){return this.#c}get calculatedSize(){return this.#y}get size(){return this.#i}get fetchMethod(){return this.#T}get dispose(){return this.#g}get disposeAfter(){return this.#m}constructor(t){let{max:e=0,ttl:r,ttlResolution:i=1,ttlAutopurge:n,updateAgeOnGet:o,updateAgeOnHas:a,allowStale:l,dispose:d,disposeAfter:p,noDisposeOnSet:g,noUpdateTTL:u,maxSize:_=0,maxEntrySize:b=0,sizeCalculation:m,fetchMethod:E,noDeleteOnFetchRejection:R,noDeleteOnStaleGet:S,allowStaleOnFetchRejection:x,allowStaleOnFetchAbort:L,ignoreFetchAbort:O}=t;if(e!==0&&!ft(e))throw new TypeError("max option must be a nonnegative integer");let X=e?Ms(e):Array;if(!X)throw new Error("invalid max value: "+e);if(this.#d=e,this.#c=_,this.maxEntrySize=b||this.#c,this.sizeCalculation=m,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(E!==void 0&&typeof E!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#T=E,this.#w=!!E,this.#r=new Map,this.#s=new Array(e).fill(void 0),this.#t=new Array(e).fill(void 0),this.#l=new X(e),this.#h=new X(e),this.#a=0,this.#n=0,this.#A=Xt.create(e),this.#i=0,this.#y=0,typeof d=="function"&&(this.#g=d),typeof p=="function"?(this.#m=p,this.#o=[]):(this.#m=void 0,this.#o=void 0),this.#_=!!this.#g,this.#u=!!this.#m,this.noDisposeOnSet=!!g,this.noUpdateTTL=!!u,this.noDeleteOnFetchRejection=!!R,this.allowStaleOnFetchRejection=!!x,this.allowStaleOnFetchAbort=!!L,this.ignoreFetchAbort=!!O,this.maxEntrySize!==0){if(this.#c!==0&&!ft(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!ft(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#P()}if(this.allowStale=!!l,this.noDeleteOnStaleGet=!!S,this.updateAgeOnGet=!!o,this.updateAgeOnHas=!!a,this.ttlResolution=ft(i)||i===0?i:1,this.ttlAutopurge=!!n,this.ttl=r||0,this.ttl){if(!ft(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#d===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#d&&!this.#c){let D="LRU_CACHE_UNBOUNDED";Li(D)&&(Ps.add(D),Fs("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",D,Dt))}}getRemainingTTL(t){return this.#r.has(t)?1/0:0}#k(){let t=new wt(this.#d),e=new wt(this.#d);this.#f=t,this.#b=e,this.#N=(n,o,a=Ct.now())=>{if(e[n]=o!==0?a:0,t[n]=o,o!==0&&this.ttlAutopurge){let l=setTimeout(()=>{this.#p(n)&&this.delete(this.#s[n])},o+1);l.unref&&l.unref()}},this.#$=n=>{e[n]=t[n]!==0?Ct.now():0},this.#S=(n,o)=>{if(t[o]){let a=t[o],l=e[o];if(!a||!l)return;n.ttl=a,n.start=l,n.now=r||i();let d=n.now-l;n.remainingTTL=a-d}};let r=0,i=()=>{let n=Ct.now();if(this.ttlResolution>0){r=n;let o=setTimeout(()=>r=0,this.ttlResolution);o.unref&&o.unref()}return n};this.getRemainingTTL=n=>{let o=this.#r.get(n);if(o===void 0)return 0;let a=t[o],l=e[o];if(!a||!l)return 1/0;let d=(r||i())-l;return a-d},this.#p=n=>{let o=e[n],a=t[n];return!!a&&!!o&&(r||i())-o>a}}#$=()=>{};#S=()=>{};#N=()=>{};#p=()=>!1;#P(){let t=new wt(this.#d);this.#y=0,this.#R=t,this.#x=e=>{this.#y-=t[e],t[e]=0},this.#D=(e,r,i,n)=>{if(this.#e(r))return 0;if(!ft(i))if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(i=n(r,e),!ft(i))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");return i},this.#H=(e,r,i)=>{if(t[e]=r,this.#c){let n=this.#c-t[e];for(;this.#y>n;)this.#O(!0)}this.#y+=t[e],i&&(i.entrySize=r,i.totalCalculatedSize=this.#y)}}#x=t=>{};#H=(t,e,r)=>{};#D=(t,e,r,i)=>{if(r||i)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#E({allowStale:t=this.allowStale}={}){if(this.#i)for(let e=this.#n;!(!this.#I(e)||((t||!this.#p(e))&&(yield e),e===this.#a));)e=this.#h[e]}*#C({allowStale:t=this.allowStale}={}){if(this.#i)for(let e=this.#a;!(!this.#I(e)||((t||!this.#p(e))&&(yield e),e===this.#n));)e=this.#l[e]}#I(t){return t!==void 0&&this.#r.get(this.#s[t])===t}*entries(){for(let t of this.#E())this.#t[t]!==void 0&&this.#s[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#s[t],this.#t[t]])}*rentries(){for(let t of this.#C())this.#t[t]!==void 0&&this.#s[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#s[t],this.#t[t]])}*keys(){for(let t of this.#E()){let e=this.#s[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#C()){let e=this.#s[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#E())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#C())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}find(t,e={}){for(let r of this.#E()){let i=this.#t[r],n=this.#e(i)?i.__staleWhileFetching:i;if(n!==void 0&&t(n,this.#s[r],this))return this.get(this.#s[r],e)}}forEach(t,e=this){for(let r of this.#E()){let i=this.#t[r],n=this.#e(i)?i.__staleWhileFetching:i;n!==void 0&&t.call(e,n,this.#s[r],this)}}rforEach(t,e=this){for(let r of this.#C()){let i=this.#t[r],n=this.#e(i)?i.__staleWhileFetching:i;n!==void 0&&t.call(e,n,this.#s[r],this)}}purgeStale(){let t=!1;for(let e of this.#C({allowStale:!0}))this.#p(e)&&(this.delete(this.#s[e]),t=!0);return t}info(t){let e=this.#r.get(t);if(e===void 0)return;let r=this.#t[e],i=this.#e(r)?r.__staleWhileFetching:r;if(i===void 0)return;let n={value:i};if(this.#f&&this.#b){let o=this.#f[e],a=this.#b[e];if(o&&a){let l=o-(Ct.now()-a);n.ttl=l,n.start=Date.now()}}return this.#R&&(n.size=this.#R[e]),n}dump(){let t=[];for(let e of this.#E({allowStale:!0})){let r=this.#s[e],i=this.#t[e],n=this.#e(i)?i.__staleWhileFetching:i;if(n===void 0||r===void 0)continue;let o={value:n};if(this.#f&&this.#b){o.ttl=this.#f[e];let a=Ct.now()-this.#b[e];o.start=Math.floor(Date.now()-a)}this.#R&&(o.size=this.#R[e]),t.unshift([r,o])}return t}load(t){this.clear();for(let[e,r]of t){if(r.start){let i=Date.now()-r.start;r.start=Ct.now()-i}this.set(e,r.value,r)}}set(t,e,r={}){if(e===void 0)return this.delete(t),this;let{ttl:i=this.ttl,start:n,noDisposeOnSet:o=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:l}=r,{noUpdateTTL:d=this.noUpdateTTL}=r,p=this.#D(t,e,r.size||0,a);if(this.maxEntrySize&&p>this.maxEntrySize)return l&&(l.set="miss",l.maxEntrySizeExceeded=!0),this.delete(t),this;let g=this.#i===0?void 0:this.#r.get(t);if(g===void 0)g=this.#i===0?this.#n:this.#A.length!==0?this.#A.pop():this.#i===this.#d?this.#O(!1):this.#i,this.#s[g]=t,this.#t[g]=e,this.#r.set(t,g),this.#l[this.#n]=g,this.#h[g]=this.#n,this.#n=g,this.#i++,this.#H(g,p,l),l&&(l.set="add"),d=!1;else{this.#v(g);let u=this.#t[g];if(e!==u){if(this.#w&&this.#e(u)){u.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:_}=u;_!==void 0&&!o&&(this.#_&&this.#g?.(_,t,"set"),this.#u&&this.#o?.push([_,t,"set"]))}else o||(this.#_&&this.#g?.(u,t,"set"),this.#u&&this.#o?.push([u,t,"set"]));if(this.#x(g),this.#H(g,p,l),this.#t[g]=e,l){l.set="replace";let _=u&&this.#e(u)?u.__staleWhileFetching:u;_!==void 0&&(l.oldValue=_)}}else l&&(l.set="update")}if(i!==0&&!this.#f&&this.#k(),this.#f&&(d||this.#N(g,i,n),l&&this.#S(l,g)),!o&&this.#u&&this.#o){let u=this.#o,_;for(;_=u?.shift();)this.#m?.(..._)}return this}pop(){try{for(;this.#i;){let t=this.#t[this.#a];if(this.#O(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#u&&this.#o){let t=this.#o,e;for(;e=t?.shift();)this.#m?.(...e)}}}#O(t){let e=this.#a,r=this.#s[e],i=this.#t[e];return this.#w&&this.#e(i)?i.__abortController.abort(new Error("evicted")):(this.#_||this.#u)&&(this.#_&&this.#g?.(i,r,"evict"),this.#u&&this.#o?.push([i,r,"evict"])),this.#x(e),t&&(this.#s[e]=void 0,this.#t[e]=void 0,this.#A.push(e)),this.#i===1?(this.#a=this.#n=0,this.#A.length=0):this.#a=this.#l[e],this.#r.delete(r),this.#i--,e}has(t,e={}){let{updateAgeOnHas:r=this.updateAgeOnHas,status:i}=e,n=this.#r.get(t);if(n!==void 0){let o=this.#t[n];if(this.#e(o)&&o.__staleWhileFetching===void 0)return!1;if(this.#p(n))i&&(i.has="stale",this.#S(i,n));else return r&&this.#$(n),i&&(i.has="hit",this.#S(i,n)),!0}else i&&(i.has="miss");return!1}peek(t,e={}){let{allowStale:r=this.allowStale}=e,i=this.#r.get(t);if(i===void 0||!r&&this.#p(i))return;let n=this.#t[i];return this.#e(n)?n.__staleWhileFetching:n}#L(t,e,r,i){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let o=new Vt,{signal:a}=r;a?.addEventListener("abort",()=>o.abort(a.reason),{signal:o.signal});let l={signal:o.signal,options:r,context:i},d=(m,E=!1)=>{let{aborted:R}=o.signal,S=r.ignoreFetchAbort&&m!==void 0;if(r.status&&(R&&!E?(r.status.fetchAborted=!0,r.status.fetchError=o.signal.reason,S&&(r.status.fetchAbortIgnored=!0)):r.status.fetchResolved=!0),R&&!S&&!E)return g(o.signal.reason);let x=_;return this.#t[e]===_&&(m===void 0?x.__staleWhileFetching?this.#t[e]=x.__staleWhileFetching:this.delete(t):(r.status&&(r.status.fetchUpdated=!0),this.set(t,m,l.options))),m},p=m=>(r.status&&(r.status.fetchRejected=!0,r.status.fetchError=m),g(m)),g=m=>{let{aborted:E}=o.signal,R=E&&r.allowStaleOnFetchAbort,S=R||r.allowStaleOnFetchRejection,x=S||r.noDeleteOnFetchRejection,L=_;if(this.#t[e]===_&&(!x||L.__staleWhileFetching===void 0?this.delete(t):R||(this.#t[e]=L.__staleWhileFetching)),S)return r.status&&L.__staleWhileFetching!==void 0&&(r.status.returnedStale=!0),L.__staleWhileFetching;if(L.__returned===L)throw m},u=(m,E)=>{let R=this.#T?.(t,n,l);R&&R instanceof Promise&&R.then(S=>m(S===void 0?void 0:S),E),o.signal.addEventListener("abort",()=>{(!r.ignoreFetchAbort||r.allowStaleOnFetchAbort)&&(m(void 0),r.allowStaleOnFetchAbort&&(m=S=>d(S,!0)))})};r.status&&(r.status.fetchDispatched=!0);let _=new Promise(u).then(d,p),b=Object.assign(_,{__abortController:o,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.set(t,b,{...l.options,status:void 0}),e=this.#r.get(t)):this.#t[e]=b,b}#e(t){if(!this.#w)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof Vt}async fetch(t,e={}){let{allowStale:r=this.allowStale,updateAgeOnGet:i=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:o=this.ttl,noDisposeOnSet:a=this.noDisposeOnSet,size:l=0,sizeCalculation:d=this.sizeCalculation,noUpdateTTL:p=this.noUpdateTTL,noDeleteOnFetchRejection:g=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:u=this.allowStaleOnFetchRejection,ignoreFetchAbort:_=this.ignoreFetchAbort,allowStaleOnFetchAbort:b=this.allowStaleOnFetchAbort,context:m,forceRefresh:E=!1,status:R,signal:S}=e;if(!this.#w)return R&&(R.fetch="get"),this.get(t,{allowStale:r,updateAgeOnGet:i,noDeleteOnStaleGet:n,status:R});let x={allowStale:r,updateAgeOnGet:i,noDeleteOnStaleGet:n,ttl:o,noDisposeOnSet:a,size:l,sizeCalculation:d,noUpdateTTL:p,noDeleteOnFetchRejection:g,allowStaleOnFetchRejection:u,allowStaleOnFetchAbort:b,ignoreFetchAbort:_,status:R,signal:S},L=this.#r.get(t);if(L===void 0){R&&(R.fetch="miss");let O=this.#L(t,L,x,m);return O.__returned=O}else{let O=this.#t[L];if(this.#e(O)){let B=r&&O.__staleWhileFetching!==void 0;return R&&(R.fetch="inflight",B&&(R.returnedStale=!0)),B?O.__staleWhileFetching:O.__returned=O}let X=this.#p(L);if(!E&&!X)return R&&(R.fetch="hit"),this.#v(L),i&&this.#$(L),R&&this.#S(R,L),O;let D=this.#L(t,L,x,m),v=D.__staleWhileFetching!==void 0&&r;return R&&(R.fetch=X?"stale":"refresh",v&&X&&(R.returnedStale=!0)),v?D.__staleWhileFetching:D.__returned=D}}get(t,e={}){let{allowStale:r=this.allowStale,updateAgeOnGet:i=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:o}=e,a=this.#r.get(t);if(a!==void 0){let l=this.#t[a],d=this.#e(l);return o&&this.#S(o,a),this.#p(a)?(o&&(o.get="stale"),d?(o&&r&&l.__staleWhileFetching!==void 0&&(o.returnedStale=!0),r?l.__staleWhileFetching:void 0):(n||this.delete(t),o&&r&&(o.returnedStale=!0),r?l:void 0)):(o&&(o.get="hit"),d?l.__staleWhileFetching:(this.#v(a),i&&this.#$(a),l))}else o&&(o.get="miss")}#U(t,e){this.#h[e]=t,this.#l[t]=e}#v(t){t!==this.#n&&(t===this.#a?this.#a=this.#l[t]:this.#U(this.#h[t],this.#l[t]),this.#U(this.#n,t),this.#n=t)}delete(t){let e=!1;if(this.#i!==0){let r=this.#r.get(t);if(r!==void 0)if(e=!0,this.#i===1)this.clear();else{this.#x(r);let i=this.#t[r];if(this.#e(i)?i.__abortController.abort(new Error("deleted")):(this.#_||this.#u)&&(this.#_&&this.#g?.(i,t,"delete"),this.#u&&this.#o?.push([i,t,"delete"])),this.#r.delete(t),this.#s[r]=void 0,this.#t[r]=void 0,r===this.#n)this.#n=this.#h[r];else if(r===this.#a)this.#a=this.#l[r];else{let n=this.#h[r];this.#l[n]=this.#l[r];let o=this.#l[r];this.#h[o]=this.#h[r]}this.#i--,this.#A.push(r)}}if(this.#u&&this.#o?.length){let r=this.#o,i;for(;i=r?.shift();)this.#m?.(...i)}return e}clear(){for(let t of this.#C({allowStale:!0})){let e=this.#t[t];if(this.#e(e))e.__abortController.abort(new Error("deleted"));else{let r=this.#s[t];this.#_&&this.#g?.(e,r,"delete"),this.#u&&this.#o?.push([e,r,"delete"])}}if(this.#r.clear(),this.#t.fill(void 0),this.#s.fill(void 0),this.#f&&this.#b&&(this.#f.fill(0),this.#b.fill(0)),this.#R&&this.#R.fill(0),this.#a=0,this.#n=0,this.#A.length=0,this.#y=0,this.#i=0,this.#u&&this.#o){let t=this.#o,e;for(;e=t?.shift();)this.#m?.(...e)}}};Zt.LRUCache=Dt});var zs=F((yn,js)=>{"use strict";var H=(...s)=>s.every(t=>t)?s.join(""):"",j=s=>s?encodeURIComponent(s):"",Bs=s=>s.toLowerCase().replace(/^\W+|\/|\W+$/g,"").replace(/\W+/g,"-"),ki={sshtemplate:({domain:s,user:t,project:e,committish:r})=>`git@${s}:${t}/${e}.git${H("#",r)}`,sshurltemplate:({domain:s,user:t,project:e,committish:r})=>`git+ssh://git@${s}/${t}/${e}.git${H("#",r)}`,edittemplate:({domain:s,user:t,project:e,committish:r,editpath:i,path:n})=>`https://${s}/${t}/${e}${H("/",i,"/",j(r||"HEAD"),"/",n)}`,browsetemplate:({domain:s,user:t,project:e,committish:r,treepath:i})=>`https://${s}/${t}/${e}${H("/",i,"/",j(r))}`,browsetreetemplate:({domain:s,user:t,project:e,committish:r,treepath:i,path:n,fragment:o,hashformat:a})=>`https://${s}/${t}/${e}/${i}/${j(r||"HEAD")}/${n}${H("#",a(o||""))}`,browseblobtemplate:({domain:s,user:t,project:e,committish:r,blobpath:i,path:n,fragment:o,hashformat:a})=>`https://${s}/${t}/${e}/${i}/${j(r||"HEAD")}/${n}${H("#",a(o||""))}`,docstemplate:({domain:s,user:t,project:e,treepath:r,committish:i})=>`https://${s}/${t}/${e}${H("/",r,"/",j(i))}#readme`,httpstemplate:({auth:s,domain:t,user:e,project:r,committish:i})=>`git+https://${H(s,"@")}${t}/${e}/${r}.git${H("#",i)}`,filetemplate:({domain:s,user:t,project:e,committish:r,path:i})=>`https://${s}/${t}/${e}/raw/${j(r||"HEAD")}/${i}`,shortcuttemplate:({type:s,user:t,project:e,committish:r})=>`${s}:${t}/${e}${H("#",r)}`,pathtemplate:({user:s,project:t,committish:e})=>`${s}/${t}${H("#",e)}`,bugstemplate:({domain:s,user:t,project:e})=>`https://${s}/${t}/${e}/issues`,hashformat:Bs},pt={};pt.github={protocols:["git:","http:","git+ssh:","git+https:","ssh:","https:"],domain:"github.com",treepath:"tree",blobpath:"blob",editpath:"edit",filetemplate:({auth:s,user:t,project:e,committish:r,path:i})=>`https://${H(s,"@")}raw.githubusercontent.com/${t}/${e}/${j(r||"HEAD")}/${i}`,gittemplate:({auth:s,domain:t,user:e,project:r,committish:i})=>`git://${H(s,"@")}${t}/${e}/${r}.git${H("#",i)}`,tarballtemplate:({domain:s,user:t,project:e,committish:r})=>`https://codeload.${s}/${t}/${e}/tar.gz/${j(r||"HEAD")}`,extract:s=>{let[,t,e,r,i]=s.pathname.split("/",5);if(!(r&&r!=="tree")&&(r||(i=s.hash.slice(1)),e&&e.endsWith(".git")&&(e=e.slice(0,-4)),!(!t||!e)))return{user:t,project:e,committish:i}}};pt.bitbucket={protocols:["git+ssh:","git+https:","ssh:","https:"],domain:"bitbucket.org",treepath:"src",blobpath:"src",editpath:"?mode=edit",edittemplate:({domain:s,user:t,project:e,committish:r,treepath:i,path:n,editpath:o})=>`https://${s}/${t}/${e}${H("/",i,"/",j(r||"HEAD"),"/",n,o)}`,tarballtemplate:({domain:s,user:t,project:e,committish:r})=>`https://${s}/${t}/${e}/get/${j(r||"HEAD")}.tar.gz`,extract:s=>{let[,t,e,r]=s.pathname.split("/",4);if(!["get"].includes(r)&&(e&&e.endsWith(".git")&&(e=e.slice(0,-4)),!(!t||!e)))return{user:t,project:e,committish:s.hash.slice(1)}}};pt.gitlab={protocols:["git+ssh:","git+https:","ssh:","https:"],domain:"gitlab.com",treepath:"tree",blobpath:"tree",editpath:"-/edit",httpstemplate:({auth:s,domain:t,user:e,project:r,committish:i})=>`git+https://${H(s,"@")}${t}/${e}/${r}.git${H("#",i)}`,tarballtemplate:({domain:s,user:t,project:e,committish:r})=>`https://${s}/${t}/${e}/repository/archive.tar.gz?ref=${j(r||"HEAD")}`,extract:s=>{let t=s.pathname.slice(1);if(t.includes("/-/")||t.includes("/archive.tar.gz"))return;let e=t.split("/"),r=e.pop();r.endsWith(".git")&&(r=r.slice(0,-4));let i=e.join("/");if(!(!i||!r))return{user:i,project:r,committish:s.hash.slice(1)}}};pt.gist={protocols:["git:","git+ssh:","git+https:","ssh:","https:"],domain:"gist.github.com",editpath:"edit",sshtemplate:({domain:s,project:t,committish:e})=>`git@${s}:${t}.git${H("#",e)}`,sshurltemplate:({domain:s,project:t,committish:e})=>`git+ssh://git@${s}/${t}.git${H("#",e)}`,edittemplate:({domain:s,user:t,project:e,committish:r,editpath:i})=>`https://${s}/${t}/${e}${H("/",j(r))}/${i}`,browsetemplate:({domain:s,project:t,committish:e})=>`https://${s}/${t}${H("/",j(e))}`,browsetreetemplate:({domain:s,project:t,committish:e,path:r,hashformat:i})=>`https://${s}/${t}${H("/",j(e))}${H("#",i(r))}`,browseblobtemplate:({domain:s,project:t,committish:e,path:r,hashformat:i})=>`https://${s}/${t}${H("/",j(e))}${H("#",i(r))}`,docstemplate:({domain:s,project:t,committish:e})=>`https://${s}/${t}${H("/",j(e))}`,httpstemplate:({domain:s,project:t,committish:e})=>`git+https://${s}/${t}.git${H("#",e)}`,filetemplate:({user:s,project:t,committish:e,path:r})=>`https://gist.githubusercontent.com/${s}/${t}/raw${H("/",j(e))}/${r}`,shortcuttemplate:({type:s,project:t,committish:e})=>`${s}:${t}${H("#",e)}`,pathtemplate:({project:s,committish:t})=>`${s}${H("#",t)}`,bugstemplate:({domain:s,project:t})=>`https://${s}/${t}`,gittemplate:({domain:s,project:t,committish:e})=>`git://${s}/${t}.git${H("#",e)}`,tarballtemplate:({project:s,committish:t})=>`https://codeload.github.com/gist/${s}/tar.gz/${j(t||"HEAD")}`,extract:s=>{let[,t,e,r]=s.pathname.split("/",4);if(r!=="raw"){if(!e){if(!t)return;e=t,t=null}return e.endsWith(".git")&&(e=e.slice(0,-4)),{user:t,project:e,committish:s.hash.slice(1)}}},hashformat:function(s){return s&&"file-"+Bs(s)}};pt.sourcehut={protocols:["git+ssh:","https:"],domain:"git.sr.ht",treepath:"tree",blobpath:"tree",filetemplate:({domain:s,user:t,project:e,committish:r,path:i})=>`https://${s}/${t}/${e}/blob/${j(r)||"HEAD"}/${i}`,httpstemplate:({domain:s,user:t,project:e,committish:r})=>`https://${s}/${t}/${e}.git${H("#",r)}`,tarballtemplate:({domain:s,user:t,project:e,committish:r})=>`https://${s}/${t}/${e}/archive/${j(r)||"HEAD"}.tar.gz`,bugstemplate:({user:s,project:t})=>null,extract:s=>{let[,t,e,r]=s.pathname.split("/",4);if(!["archive"].includes(r)&&(e&&e.endsWith(".git")&&(e=e.slice(0,-4)),!(!t||!e)))return{user:t,project:e,committish:s.hash.slice(1)}}};for(let[s,t]of Object.entries(pt))pt[s]=Object.assign({},ki,t);js.exports=pt});var Se=F((An,qs)=>{var Ni=q("url"),Ce=(s,t,e)=>{let r=s.indexOf(e);return s.lastIndexOf(t,r>-1?r:1/0)},Gs=s=>{try{return new Ni.URL(s)}catch{}},Di=(s,t)=>{let e=s.indexOf(":"),r=s.slice(0,e+1);if(Object.prototype.hasOwnProperty.call(t,r))return s;let i=s.indexOf("@");return i>-1?i>e?`git+ssh://${s}`:s:s.indexOf("//")===e+1?s:`${s.slice(0,e+1)}//${s.slice(e+1)}`},Ii=s=>{let t=Ce(s,"@","#"),e=Ce(s,":","#");return e>t&&(s=s.slice(0,e)+"/"+s.slice(e+1)),Ce(s,":","#")===-1&&s.indexOf("//")===-1&&(s=`git+ssh://${s}`),s};qs.exports=(s,t)=>{let e=t?Di(s,t):s;return Gs(e)||Gs(Ii(e))}});var Qs=F((Rn,Ks)=>{"use strict";var Ui=Se(),Pi=s=>{let t=s.indexOf("#"),e=s.indexOf("/"),r=s.indexOf("/",e+1),i=s.indexOf(":"),n=/\s/.exec(s),o=s.indexOf("@"),a=!n||t>-1&&n.index>t,l=o===-1||t>-1&&o>t,d=i===-1||t>-1&&i>t,p=r===-1||t>-1&&r>t,g=e>0,u=t>-1?s[t-1]!=="/":!s.endsWith("/"),_=!s.startsWith(".");return a&&g&&u&&_&&l&&d&&p};Ks.exports=(s,t,{gitHosts:e,protocols:r})=>{if(!s)return;let i=Pi(s)?`github:${s}`:s,n=Ui(i,r);if(!n)return;let o=e.byShortcut[n.protocol],a=e.byDomain[n.hostname.startsWith("www.")?n.hostname.slice(4):n.hostname],l=o||a;if(!l)return;let d=e[o||a],p=null;r[n.protocol]?.auth&&(n.username||n.password)&&(p=`${n.username}${n.password?":"+n.password:""}`);let g=null,u=null,_=null,b=null;try{if(o){let m=n.pathname.startsWith("/")?n.pathname.slice(1):n.pathname,E=m.indexOf("@");E>-1&&(m=m.slice(E+1));let R=m.lastIndexOf("/");R>-1?(u=decodeURIComponent(m.slice(0,R)),u||(u=null),_=decodeURIComponent(m.slice(R+1))):_=decodeURIComponent(m),_.endsWith(".git")&&(_=_.slice(0,-4)),n.hash&&(g=decodeURIComponent(n.hash.slice(1))),b="shortcut"}else{if(!d.protocols.includes(n.protocol))return;let m=d.extract(n);if(!m)return;u=m.user&&decodeURIComponent(m.user),_=decodeURIComponent(m.project),g=decodeURIComponent(m.committish),b=r[n.protocol]?.name||n.protocol.slice(0,-1)}}catch(m){if(m instanceof URIError)return;throw m}return[l,u,p,_,g,b,t]}});var Vs=F((bn,Xs)=>{"use strict";var{LRUCache:Fi}=Ws(),Mi=zs(),Wi=Qs(),Bi=Se(),we=new Fi({max:1e3}),dt,It,G,Q,ut=class{constructor(t,e,r,i,n,o,a={}){bt(this,G);Object.assign(this,ot(ut,dt)[t],{type:t,user:e,auth:r,project:i,committish:n,default:o,opts:a})}static addHost(t,e){ot(ut,dt)[t]=e,ot(ut,dt).byDomain[e.domain]=t,ot(ut,dt).byShortcut[`${t}:`]=t,ot(ut,It)[`${t}:`]={name:t}}static fromUrl(t,e){if(typeof t!="string")return;let r=t+JSON.stringify(e||{});if(!we.has(r)){let i=Wi(t,e,{gitHosts:ot(ut,dt),protocols:ot(ut,It)});we.set(r,i?new ut(...i):void 0)}return we.get(r)}static parseUrl(t){return Bi(t)}hash(){return this.committish?`#${this.committish}`:""}ssh(t){return K(this,G,Q).call(this,this.sshtemplate,t)}sshurl(t){return K(this,G,Q).call(this,this.sshurltemplate,t)}browse(t,...e){return typeof t!="string"?K(this,G,Q).call(this,this.browsetemplate,t):typeof e[0]!="string"?K(this,G,Q).call(this,this.browsetreetemplate,{...e[0],path:t}):K(this,G,Q).call(this,this.browsetreetemplate,{...e[1],fragment:e[0],path:t})}browseFile(t,...e){return typeof e[0]!="string"?K(this,G,Q).call(this,this.browseblobtemplate,{...e[0],path:t}):K(this,G,Q).call(this,this.browseblobtemplate,{...e[1],fragment:e[0],path:t})}docs(t){return K(this,G,Q).call(this,this.docstemplate,t)}bugs(t){return K(this,G,Q).call(this,this.bugstemplate,t)}https(t){return K(this,G,Q).call(this,this.httpstemplate,t)}git(t){return K(this,G,Q).call(this,this.gittemplate,t)}shortcut(t){return K(this,G,Q).call(this,this.shortcuttemplate,t)}path(t){return K(this,G,Q).call(this,this.pathtemplate,t)}tarball(t){return K(this,G,Q).call(this,this.tarballtemplate,{...t,noCommittish:!1})}file(t,e){return K(this,G,Q).call(this,this.filetemplate,{...e,path:t})}edit(t,e){return K(this,G,Q).call(this,this.edittemplate,{...e,path:t})}getDefaultRepresentation(){return this.default}toString(t){return this.default&&typeof this[this.default]=="function"?this[this.default](t):this.sshurl(t)}},xt=ut;dt=new WeakMap,It=new WeakMap,G=new WeakSet,Q=function(t,e){if(typeof t!="function")return null;let r={...this,...this.opts,...e};r.path||(r.path=""),r.path.startsWith("/")&&(r.path=r.path.slice(1)),r.noCommittish&&(r.committish=null);let i=t(r);return r.noGitPlus&&i.startsWith("git+")?i.slice(4):i},bt(xt,dt,{byShortcut:{},byDomain:{}}),bt(xt,It,{"git+ssh:":{name:"sshurl"},"ssh:":{name:"sshurl"},"git+https:":{name:"https",auth:!0},"git:":{auth:!0},"http:":{auth:!0},"https:":{auth:!0},"git+http:":{auth:!0}});for(let[s,t]of Object.entries(Mi))xt.addHost(s,t);Xs.exports=xt});var qi={};mr(qi,{default:()=>Gi});var ar=q("@yarnpkg/core");var ee=q("@yarnpkg/cli"),W=q("@yarnpkg/core"),J=q("clipanion"),xe=Rt(Is()),or=Rt(q("path")),te=Rt(q("semver")),At=Rt(q("typanion"));var vt=q("@yarnpkg/core"),er=q("@yarnpkg/plugin-essentials");var Zs=Rt(Vs()),Ut=Rt(q("semver")),Ys=Boolean;function Js({raw:s}){if(s.homepage)return s.homepage;let t=s.repository,e=typeof t=="string"?t:typeof t=="object"&&typeof t.url=="string"?t.url:null,r=e?(0,Zs.fromUrl)(e):void 0,i=r?.committish?`#${r.committish}`:"";return r?`https://${r.domain}/${r.user}/${r.project}${i}`:e}function tr(s,t){return Ut.default.parse(t).prerelease.length?Ut.default.lt(s,t):Ut.default.lt(Ut.default.coerce(s),t)}var Yt=class{constructor(t,e,r,i){this.configuration=t;this.project=e;this.workspace=r;this.cache=i}async fetch({descriptor:t,includeRange:e,includeURL:r,pkg:i}){let[n,o,a]=await Promise.all([this.suggest(i,"latest"),e?this.suggest(i,t.range):Promise.resolve(),r?this.fetchURL(i):Promise.resolve()]);if(!n){let l=vt.structUtils.prettyIdent(this.configuration,i);throw new Error(`Could not fetch candidate for ${l}.`)}return{latest:n.range,range:o?.range,url:a??void 0}}suggest(t,e){return er.suggestUtils.fetchDescriptorFrom(t,e,{cache:this.cache,preserveModifier:!1,project:this.project,workspace:this.workspace})}async fetchURL(t){let e=this.configuration.makeFetcher(),r=await e.fetch(t,{cache:this.cache,cacheOptions:{skipIntegrityCheck:!0},checksums:this.project.storedChecksums,fetcher:e,project:this.project,report:new vt.ThrowReport}),i;try{i=await vt.Manifest.find(r.prefixPath,{baseFs:r.packageFs})}finally{r.releaseFs?.()}return Js(i)}};var Jt=q("@yarnpkg/core"),ji=/^([0-9]+\.)([0-9]+\.)(.+)$/,sr=["name","current","range","latest","workspace","type","url"],Pt=class{constructor(t,e,r,i,n){this.format=t;this.writer=e;this.configuration=r;this.dependencies=i;this.extraColumns=n}sizes=null;headers={current:"Current",latest:"Latest",name:"Package",range:"Range",type:"Package Type",url:"URL",workspace:"Workspace"};print(){this.sizes=this.getColumnSizes(),this.printHeader(),this.dependencies.forEach(t=>{let e=this.getDiffColor(t.severity.latest),r=this.getDiffColor(t.severity.range);this.printRow({current:t.current.padEnd(this.sizes.current),latest:this.formatVersion(t,"latest",e),name:this.applyColor(t.name.padEnd(this.sizes.name),e),range:this.formatVersion(t,"range",r),type:t.type.padEnd(this.sizes.type),url:t.url?.padEnd(this.sizes.url),workspace:t.workspace?.padEnd(this.sizes.workspace)})})}applyColor(t,e){return e?Jt.formatUtils.pretty(this.configuration,t,e):t}formatVersion(t,e,r){let i=t[e]?.padEnd(this.sizes[e]);if(!i)return;let n=i.match(ji);if(!n||!r)return i;let o=["red","yellow","green"].indexOf(r)+1,a=n.slice(1,o).join(""),l=n.slice(o).join("");return a+Jt.formatUtils.pretty(this.configuration,this.applyColor(l,r),"bold")}getDiffColor(t){return t?{major:"red",minor:"yellow",patch:"green"}[t]:null}getColumnSizes(){let t=sr.reduce((e,r)=>({...e,[r]:this.headers[r].length}),{});for(let e of this.dependencies)for(let[r,i]of Object.entries(e)){let n=t[r],o=(i||"").length;t[r]=n>o?n:o}return t}formatColumnHeader(t){return Jt.formatUtils.pretty(this.configuration,this.headers[t].padEnd(this.sizes[t]),"bold")}printHeader(){this.printRow({current:this.formatColumnHeader("current"),latest:this.formatColumnHeader("latest"),name:this.formatColumnHeader("name"),range:this.formatColumnHeader("range"),type:this.formatColumnHeader("type"),url:this.formatColumnHeader("url"),workspace:this.formatColumnHeader("workspace")}),this.format==="markdown"&&this.printRow(Object.keys(this.sizes).reduce((t,e)=>({...t,[e]:"".padEnd(this.sizes[e],"-")}),{}))}printRow(t){let e=this.format==="markdown",r=sr.filter(i=>this.extraColumns[i]??!0).map(i=>t[i]).join(e?" | ":" ");this.writer(e?`| ${r} |`:r.trim())}};var $e=["dependencies","devDependencies"],rr=["major","minor","patch"],ir=["text","json","markdown"];var nr="\u2728 All your dependencies are up to date!",Tt=class extends ee.BaseCommand{patterns=J.Option.Rest();workspace=J.Option.Array("-w,--workspace",{description:"Only search for dependencies in the specified workspaces. If no workspaces are specified, only searches for outdated dependencies in the current workspace.",validator:At.default.isArray(At.default.isString())});check=J.Option.Boolean("-c,--check",!1,{description:"Exit with exit code 1 when outdated dependencies are found"});format=J.Option.String("--format","text",{description:"The format of the output (text|json|markdown)",validator:At.default.isEnum(ir)});json=J.Option.Boolean("--json",!1,{description:"Format the output as JSON"});severity=J.Option.Array("-s,--severity",{description:"Filter results based on the severity of the update",validator:At.default.isArray(At.default.isEnum(rr))});type=J.Option.String("-t,--type",{description:"Filter results based on the dependency type",validator:At.default.isEnum($e)});_includeURL=J.Option.Boolean("--url",{description:"Include the homepage URL of each package in the output"});includeRange=J.Option.Boolean("--range",!1,{description:"Include the latest version of the package which satisfies the current range specified in the manifest."});async execute(){let{cache:t,configuration:e,project:r,workspace:i}=await this.loadProject(),n=new Yt(e,r,i,t),o=this.getWorkspaces(r),a=this.getDependencies(e,o);if(this.format!=="text"||this.json){let d=await this.getOutdatedDependencies(e,r,n,a);return this.format==="json"||this.json?this.writeJson(d):this.writeMarkdown(e,r,d),this.check&&d.length?1:0}return(await W.StreamReport.start({configuration:e,stdout:this.context.stdout},async d=>{await this.checkOutdatedDependencies(e,r,a,n,d)})).exitCode()}includeURL(t){return this._includeURL??t.get("outdatedIncludeUrl")}writeJson(t){let e=t.map(r=>({...r,severity:r.severity.latest}));this.context.stdout.write(JSON.stringify(e)+` 8 | `)}writeMarkdown(t,e,r){if(!r.length){this.context.stdout.write(nr+` 9 | `);return}new Pt("markdown",n=>this.context.stdout.write(n+` 10 | `),t,r,{range:this.includeRange,url:this.includeURL(t),workspace:this.includeWorkspace(e)}).print()}async checkOutdatedDependencies(t,e,r,i,n){let o=null;await n.startTimerPromise("Checking for outdated dependencies",async()=>{let a=r.length,l=W.StreamReport.progressViaCounter(a);n.reportProgress(l),o=await this.getOutdatedDependencies(t,e,i,r,l)}),n.reportSeparator(),o.length?(new Pt("text",l=>n.reportInfo(W.MessageName.UNNAMED,l),t,o,{range:this.includeRange,url:this.includeURL(t),workspace:this.includeWorkspace(e)}).print(),n.reportSeparator(),this.printOutdatedCount(n,o.length)):n.reportInfo(W.MessageName.UNNAMED,W.formatUtils.pretty(t,nr,"green"))}async loadProject(){let t=await W.Configuration.find(this.context.cwd,this.context.plugins),[e,{project:r,workspace:i}]=await Promise.all([W.Cache.find(t),W.Project.find(t,this.context.cwd)]);if(await r.restoreInstallState(),!i)throw new ee.WorkspaceRequiredError(r.cwd,this.context.cwd);return{cache:e,configuration:t,project:r,workspace:i}}getWorkspaces(t){let e=this.workspace;return e?e[0]==="."?t.workspaces.filter(r=>r.cwd===this.context.cwd):t.workspaces.filter(r=>{let i=[...e,...e.map(n=>or.default.join(this.context.cwd,n))];return xe.default.some([this.getWorkspaceName(r),r.cwd],i)}):t.workspaces}includeWorkspace(t){return t.workspaces.length>1}get dependencyTypes(){return this.type?[this.type]:$e}getDependencies(t,e){let r=[];for(let n of e){let{anchoredLocator:o,project:a}=n,l=a.storedPackages.get(o.locatorHash);l||this.throw(t,o);for(let d of this.dependencyTypes)for(let p of n.manifest[d].values()){let{range:g}=p;if(g.includes(":")&&!/(npm|patch):/.test(g))continue;let u=l.dependencies.get(p.identHash);u||this.throw(t,p);let _=a.storedResolutions.get(u.descriptorHash);_||this.throw(t,u);let b=a.storedPackages.get(_);b||this.throw(t,u),!n.project.tryWorkspaceByLocator(b)&&(b.reference.includes("github.com")||r.push({dependencyType:d,descriptor:p,name:W.structUtils.stringifyIdent(p),pkg:b,workspace:n}))}}if(!this.patterns.length)return r;let i=r.filter(({name:n})=>xe.default.isMatch(n,this.patterns));if(!i.length)throw new J.UsageError(`Pattern ${W.formatUtils.prettyList(t,this.patterns,W.formatUtils.Type.CODE)} doesn't match any packages referenced by any workspace`);return i}throw(t,e){let r=W.structUtils.prettyIdent(t,e);throw new Error(`Package for ${r} not found in the project`)}getSeverity(t,e){let r=te.default.coerce(t),i=te.default.coerce(e);return te.default.eq(r,i)?null:r.major===0||i.major>r.major?"major":i.minor>r.minor?"minor":"patch"}async getOutdatedDependencies(t,e,r,i,n){let o=i.map(async({dependencyType:a,descriptor:l,name:d,pkg:p,workspace:g})=>{let{latest:u,range:_,url:b}=await r.fetch({descriptor:l,includeRange:this.includeRange,includeURL:this.includeURL(t),pkg:p});if(n?.tick(),tr(p.version,u))return{current:p.version,latest:u,name:d,range:_,severity:{latest:this.getSeverity(p.version,u),range:_?this.getSeverity(p.version,_):null},type:a,url:b,workspace:this.includeWorkspace(e)?this.getWorkspaceName(g):void 0}});return(await Promise.all(o)).filter(Ys).filter(a=>this.severity?.includes(a.severity.latest)??!0).sort((a,l)=>a.name.localeCompare(l.name))}getWorkspaceName(t){return t.manifest.name?W.structUtils.stringifyIdent(t.manifest.name):t.computeCandidateName()}printOutdatedCount(t,e){let r=[W.MessageName.UNNAMED,e===1?"1 dependency is out of date":`${e} dependencies are out of date`];this.check?t.reportError(...r):t.reportWarning(...r)}};re(Tt,"paths",[["outdated"]]),re(Tt,"usage",J.Command.Usage({description:"view outdated dependencies",details:` 11 | This command finds outdated dependencies in a project and prints the result in a table or JSON format. 12 | 13 | This command accepts glob patterns as arguments to filter the output. Make sure to escape the patterns, to prevent your own shell from trying to expand them. 14 | `,examples:[["View outdated dependencies","yarn outdated"],["View outdated dependencies with the `@babel` scope","yarn outdated '@babel/*'"],["Filter results to only include devDependencies","yarn outdated --type devDependencies"],["Filter results to only include major version updates","yarn outdated --severity major"]]}));var zi={commands:[Tt],configuration:{outdatedIncludeUrl:{default:!1,description:"If true, the outdated command will include the package homepage URL by default",type:ar.SettingsType.BOOLEAN}}},Gi=zi;return yr(qi);})(); 15 | /*! 16 | * fill-range 17 | * 18 | * Copyright (c) 2014-present, Jon Schlinkert. 19 | * Licensed under the MIT License. 20 | */ 21 | /*! 22 | * is-number 23 | * 24 | * Copyright (c) 2014-present, Jon Schlinkert. 25 | * Released under the MIT License. 26 | */ 27 | /*! 28 | * to-regex-range 29 | * 30 | * Copyright (c) 2015-present, Jon Schlinkert. 31 | * Released under the MIT License. 32 | */ 33 | return plugin; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | plugins: 4 | - checksum: 53df621960dbcb9cc3953b45376e0d7e0fbcb870eec71ebb8ffa575c2e834349fdcfa255c46b8fa3fff2c65f26e55c7339c2cb57ee80f92d62c9e181bcb7792d 5 | path: .yarn/plugins/@yarnpkg/plugin-outdated.cjs 6 | spec: "https://mskelton.dev/yarn-outdated/v4" 7 | 8 | yarnPath: .yarn/releases/yarn-4.0.2.cjs 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | The changelog is automatically updated using 4 | [semantic-release](https://github.com/semantic-release/semantic-release). You 5 | can see it on the 6 | [releases page](https://github.com/lariat-js/playwright/releases). 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and 9 | expression, level of experience, education, socio-economic status, nationality, 10 | personal appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or reject 41 | comments, commits, code, wiki edits, issues, and other contributions that are 42 | not aligned to this Code of Conduct, or to ban temporarily or permanently any 43 | contributor for other behaviors that they deem inappropriate, threatening, 44 | offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at . All complaints will be reviewed and 59 | investigated and will result in a response that is deemed necessary and 60 | appropriate to the circumstances. The project team is obligated to maintain 61 | confidentiality with regard to the reporter of an incident. Further details of 62 | specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 71 | version 1.4, available at 72 | https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 73 | 74 | [homepage]: https://www.contributor-covenant.org 75 | 76 | For answers to common questions about this code of conduct, see 77 | https://www.contributor-covenant.org/faq 78 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Code reviews 7 | 8 | All submissions, including submissions by project members, require review. We 9 | use GitHub pull requests for this purpose. Consult 10 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 11 | information on using pull requests. 12 | 13 | ## Tips 14 | 15 | - Smaller changes are easier to review 16 | - Give the PR a meaningful title and description with context surrounding the 17 | changes 18 | - To close an issue automatically after a PR is merged, use keywords "fix", 19 | "close", or "resolve" in the PR description, e.g. fix #1337. 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2023, Lariat Team 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lariat for Playwright 2 | 3 | [![Build](https://github.com/lariat-js/playwright/actions/workflows/build.yml/badge.svg)](https://github.com/lariat-js/playwright/actions/workflows/build.yml) 4 | [![npm](https://img.shields.io/npm/v/@lariat/playwright)](https://www.npmjs.com/package/@lariat/playwright) 5 | 6 | Page object framework for [Playwright](https://playwright.dev). 7 | 8 | ## Installation 9 | 10 | npm 11 | 12 | ```sh 13 | npm install @lariat/playwright 14 | ``` 15 | 16 | Yarn 17 | 18 | ```sh 19 | yarn add @lariat/playwright 20 | ``` 21 | 22 | pnpm 23 | 24 | ```sh 25 | pnpm add @lariat/playwright 26 | ``` 27 | 28 | Bun 29 | 30 | ```sh 31 | bun add @lariat/playwright 32 | ``` 33 | 34 | ## Basic Usage 35 | 36 | At the core of Lariat is the `Collection` class. This class is used to represent 37 | a collection of elements in a page or section of a page and can include 38 | associated utility methods for interacting with those elements. 39 | 40 | To create your own collections, simply create a class which extends the 41 | `Collection` class. You can then define elements using the `Collection.el()` 42 | method which we will explore more in a moment. 43 | 44 | ```ts 45 | import Collection from '@lariat/playwright' 46 | 47 | class TodoPage extends Collection { 48 | input = this.el('#todo-input') 49 | } 50 | ``` 51 | 52 | With your collection defined, you can instantiate it in your test to access the 53 | elements. 54 | 55 | ```ts 56 | test('create a todo', async ({ page }) => { 57 | const todoPage = new TodoPage(page) 58 | await todoPage.input.fill('Finish the website') 59 | }) 60 | ``` 61 | 62 | ## Elements 63 | 64 | Elements are defined in collections using the `Collection.el()` method. 65 | 66 | ```ts 67 | class TodoPage extends Collection { 68 | saveButton = this.el('#save-button') 69 | } 70 | ``` 71 | 72 | Elements are represented using Playwright 73 | [locators](https://playwright.dev/docs/api/class-locator) . 74 | 75 | ```ts 76 | const todoPage = new TodoPage(page) 77 | await todoPage.saveButton.click() 78 | ``` 79 | 80 | ### `has` and `hasText` 81 | 82 | The `has` and `hasText` locator options can be passed to `Collection.el()` to 83 | match elements that contain a given locator or text. 84 | 85 | ```ts 86 | class TodoPage extends Collection { 87 | buttonWithIcon = this.el('button', { has: this.el('svg') }) 88 | saveButton = this.el('button', { hasText: 'Save' }) 89 | } 90 | ``` 91 | 92 | ### Dynamic selectors 93 | 94 | Because collections in Lariat are plain JavaScript classes, you can easily 95 | create elements with dynamic selectors. Consider a todo list where we find an 96 | item based on it's name. Our collection might look something like this: 97 | 98 | ```ts 99 | class TodoPage extends Collection { 100 | item = (name: string) => this.el(`#todo-item[data-name="${name}"]`) 101 | } 102 | 103 | const todoPage = new TodoPage(page) 104 | const item = todoPage.item('Finish the website') 105 | await item.click() 106 | ``` 107 | 108 | ### Portals 109 | 110 | Sometimes, the DOM structure of a page might not match the visual structure 111 | exactly. For example, if you use React's `createPortal` function you can render 112 | an element outside the main React tree. To support these use cases, Lariat 113 | allows you to pass a `portal` option to `Collection.el()` to indicate that the 114 | element should not be based off the `root` element. 115 | 116 | ```ts 117 | class TodoPage extends Collection { 118 | modal = this.el('#modal', { portal: true }) 119 | } 120 | ``` 121 | 122 | ## Utility methods 123 | 124 | Because collections are plain JavaScript classes, you can easily add utility 125 | methods to your collections. 126 | 127 | ```ts 128 | class TodoPage extends Collection { 129 | input = this.el('#todo-input') 130 | saveButton = this.el('#save-button') 131 | 132 | async create(name: string) { 133 | await this.input.fill(name) 134 | await this.input.click() 135 | } 136 | } 137 | 138 | const todoPage = new TodoPage(page) 139 | await todoPage.create('Finish the website') 140 | ``` 141 | 142 | ## Nested collections 143 | 144 | So far, we've shown examples of simple collections, but Lariat also gives you 145 | the ability to nest collections inside each other. With this approach, you can 146 | create a page object structure that more closely resembles your page layout. 147 | 148 | To nest a collection, use the `Collection.nest()` method and pass the nested 149 | collection class and the root of the nested collection. 150 | 151 | ```ts 152 | class TodoPage extends Collection { 153 | field = this.nest(TextField, '#todo-field') 154 | } 155 | 156 | const todoPage = new TodoPage(page) 157 | await todoPage.field.input.fill('Finish the website') 158 | ``` 159 | 160 | If your nested collection is used merely to group a set of related elements 161 | together, you can use the parent's `root` property as the root of the child 162 | collection. 163 | 164 | ```ts 165 | class TodoPage extends Collection { 166 | field = this.nest(TextField, this.root) 167 | } 168 | ``` 169 | 170 | If your nested collection exists outside the DOM structure of the parent 171 | collection, you can use the parent's `frame` property as the root of the child 172 | collection. This behaves very similarly to the `portal` option for 173 | `Collection.el()`. 174 | 175 | ```ts 176 | class TodoPage extends Collection { 177 | modal = this.nest(Modal, this.frame) 178 | } 179 | ``` 180 | 181 | ### `first`, `last`, and `nth` 182 | 183 | In some cases, you may have a nested collection where multiple instances exist 184 | on the page. For example, a todo list may contain multiple todo items each of 185 | which are represented as a collection. To make these scenarios easier, Lariat 186 | provides `first`, `last`, and `nth` methods which will return a new instance of 187 | the nested collection scoped to that specific item. 188 | 189 | ```ts 190 | class TodoPage extends Collection { 191 | item = this.nest(TodoItem, '.todo-item') 192 | } 193 | 194 | const todoPage = new TodoPage(page) 195 | const firstItem = todoPage.item.first() 196 | const secondItem = todoPage.item.nth(1) 197 | const lastItem = todoPage.item.last() 198 | ``` 199 | 200 | ## Frames 201 | 202 | Lariat has utilities for working with frames thanks to Playwright's 203 | [`FrameLocator`](https://playwright.dev/docs/api/class-framelocator). 204 | 205 | The simplest way to access an element in a frame is by using the `frame` option 206 | of `Collection.el`. Simply pass a string as a selector for the frame and Lariat 207 | will take care of the rest. 208 | 209 | ```ts 210 | class FramePage extends Collection { 211 | frameHeader = this.el('h1', { frame: '#my-frame' }) 212 | } 213 | ``` 214 | 215 | However, if you need to access multiple elements in a frame, you can use 216 | `Collection.nest` with a `FrameLocator`. 217 | 218 | ```ts 219 | class MyFrame extends Collection { 220 | header = this.el('h1') 221 | content = this.el('main') 222 | } 223 | 224 | class FramePage extends Collection { 225 | myFrame = this.nest(MyFrame, this.page.frameLocator('#my-frame')) 226 | } 227 | ``` 228 | 229 | You can use a similar method to instantiate collections with a `FrameLocator` as 230 | the root. 231 | 232 | ```ts 233 | class MyFrame extends Collection { 234 | header = this.el('h1') 235 | content = this.el('main') 236 | } 237 | 238 | new MyFrame(page.frameLocator('#my-frame')) 239 | ``` 240 | 241 | ## Accessing the page or frame 242 | 243 | Lariat makes it easy to access the page or frame that a collection is associated 244 | with. 245 | 246 | ```ts 247 | class TodoPage extends Collection { 248 | input = this.el('#todo-input') 249 | } 250 | 251 | const todoPage = new TodoPage(page.locator('#my-page')) 252 | await todoPage.frame.goto('https://google.com') 253 | await todoPage.page.mouse.down() 254 | ``` 255 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lariat/playwright", 3 | "version": "0.0.0-semantically-released", 4 | "description": "Page object framework for end-to-end testing in Playwright.", 5 | "publishConfig": { 6 | "access": "public" 7 | }, 8 | "author": "Lariat Team", 9 | "license": "ISC", 10 | "packageManager": "yarn@4.0.2", 11 | "repository": "github:lariat-js/playwright", 12 | "homepage": "https://github.com/lariat-js/playwright#readme", 13 | "bugs": { 14 | "url": "https://github.com/lariat-js/playwright/issues" 15 | }, 16 | "keywords": [ 17 | "lariat", 18 | "page-object-model", 19 | "end-to-end-testing", 20 | "playwright", 21 | "playwright-test" 22 | ], 23 | "type": "module", 24 | "types": "./dist/index.d.ts", 25 | "exports": { 26 | "types": "./dist/index.d.ts", 27 | "import": "./dist/index.js", 28 | "require": "./dist/index.cjs" 29 | }, 30 | "files": [ 31 | "dist" 32 | ], 33 | "scripts": { 34 | "lint": "eslint .", 35 | "test": "playwright test", 36 | "build": "tsup ./src/index.ts --format cjs,esm --dts", 37 | "release": "./scripts/release.sh" 38 | }, 39 | "peerDependencies": { 40 | "@playwright/test": ">=1.28.0" 41 | }, 42 | "devDependencies": { 43 | "@babel/core": "^7.20.12", 44 | "@babel/eslint-parser": "^7.19.1", 45 | "@mskelton/semantic-release-config": "^1.0.1", 46 | "@playwright/test": "^1.30.0", 47 | "@typescript-eslint/eslint-plugin": "^5.49.0", 48 | "@typescript-eslint/parser": "^5.49.0", 49 | "eslint": "^8.32.0", 50 | "eslint-config-widen": "^1.1.0", 51 | "eslint-plugin-playwright": "^0.12.0", 52 | "eslint-plugin-sort": "^2.4.0", 53 | "eslint-plugin-widen": "^1.0.0", 54 | "prettier": "^2.8.3", 55 | "semantic-release": "^23.0.2", 56 | "tsup": "^6.5.0", 57 | "typescript": "^4.9.4" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { PlaywrightTestConfig } from '@playwright/test' 2 | 3 | const config: PlaywrightTestConfig = { 4 | forbidOnly: !!process.env.CI, 5 | retries: process.env.CI ? 2 : 0, 6 | use: { 7 | screenshot: 'only-on-failure', 8 | trace: 'on-first-retry', 9 | }, 10 | } 11 | 12 | export default config 13 | -------------------------------------------------------------------------------- /src/Collection.ts: -------------------------------------------------------------------------------- 1 | import type { Frame, FrameLocator, Locator, Page } from '@playwright/test' 2 | import { enhance, NestedCollection } from './enhance.js' 3 | import { Handle, isLocator } from './utils.js' 4 | 5 | export interface SelectorOptions { 6 | /** 7 | * When defined, creates a frame locator which the element will be nested 8 | * inside of. 9 | */ 10 | frame?: string 11 | /** 12 | * When true, the locator will be based off the `frame`, rather than the 13 | * `root` thus escaping from any collection nesting. This is useful to 14 | * represent a page structure whose visual appearance differs from it's 15 | * DOM structure. 16 | * 17 | * @default false 18 | */ 19 | portal?: boolean 20 | } 21 | 22 | type Method = 23 | | 'locator' 24 | | 'getByAltText' 25 | | 'getByLabel' 26 | | 'getByPlaceholder' 27 | | 'getByRole' 28 | | 'getByTestId' 29 | | 'getByText' 30 | | 'getByTitle' 31 | 32 | // Using an empty object `{}` as a type is typically a bad practice, but an 33 | // empty interface is fine. 34 | interface EmptyObject {} 35 | 36 | // Extract the first argument for a given page method. This can't just be 37 | // `string` since `getByRole` is more strict. 38 | type Arg = Parameters[0] 39 | 40 | // Extract additional page objects if present and add the Lariat selector options 41 | type Options = (Parameters[1] extends undefined 42 | ? EmptyObject 43 | : Parameters[1]) & 44 | SelectorOptions 45 | 46 | interface EnhancedPageMethod { 47 | (arg: Arg, options?: Options): Locator 48 | } 49 | 50 | export class Collection { 51 | protected getByAltText: EnhancedPageMethod<'getByAltText'> 52 | protected getByLabel: EnhancedPageMethod<'getByLabel'> 53 | protected getByPlaceholder: EnhancedPageMethod<'getByPlaceholder'> 54 | protected getByRole: EnhancedPageMethod<'getByRole'> 55 | protected getByTestId: EnhancedPageMethod<'getByTestId'> 56 | protected getByText: EnhancedPageMethod<'getByText'> 57 | protected getByTitle: EnhancedPageMethod<'getByTitle'> 58 | 59 | constructor(public root: T) { 60 | this.getByAltText = this.enhanceMethod('getByAltText') 61 | this.getByLabel = this.enhanceMethod('getByLabel') 62 | this.getByPlaceholder = this.enhanceMethod('getByPlaceholder') 63 | this.getByRole = this.enhanceMethod('getByRole') 64 | this.getByTestId = this.enhanceMethod('getByTestId') 65 | this.getByText = this.enhanceMethod('getByText') 66 | this.getByTitle = this.enhanceMethod('getByTitle') 67 | } 68 | 69 | /** 70 | * Retrieve a locator to a given element on the page identified by the 71 | * selector. 72 | * 73 | * @param selector - The selector that identifies the element. 74 | * @param options - Options for how to build the locator. 75 | */ 76 | protected el( 77 | selector: string, 78 | { frame, portal, ...options }: Options<'locator'> = {} 79 | ): Locator { 80 | return this.getParent(frame, portal).locator(selector, options) 81 | } 82 | 83 | /** 84 | * Nest another collection inside of the current collection. Locators in the 85 | * nested collection will be based on the `root` argument which can be 86 | * customized to be a selector, locator, page, etc. 87 | * 88 | * @param collection - Uninstantiated collection class to nest. 89 | * @param root - The root of the nested collection. This could be a static 90 | * string, an element from the parent collection, or the collection's frame. 91 | * 92 | * @example this.nest(TextField, '#my-text-field') 93 | * @example this.nest(TextField, this.form) 94 | * @example this.nest(TextField, this.frame) 95 | */ 96 | protected nest( 97 | collection: new (root: Locator) => U, 98 | root: string | Locator 99 | ): NestedCollection 100 | protected nest( 101 | collection: new (root: FrameLocator) => U, 102 | root: string | FrameLocator 103 | ): NestedCollection 104 | protected nest( 105 | collection: new (root: Root) => U, 106 | root: Root 107 | ): U 108 | protected nest( 109 | collection: new (root: Handle) => U, 110 | root: string | Root 111 | ): NestedCollection | U { 112 | const rootElement = typeof root === 'string' ? this.el(root) : root 113 | const instance = new collection(rootElement) 114 | 115 | // If the root element is a locator, it can use the `nth`, `first`, and 116 | // `last` methods and thus it should be enhanced. 117 | return isLocator(rootElement) 118 | ? enhance(collection, rootElement, instance) 119 | : instance 120 | } 121 | 122 | /** 123 | * Returns the frame that the collection is attached to. This can be used when 124 | * nesting a collection if the nested collection's locators elements should 125 | * be based off the page or frame rather than the parent collection's root. 126 | * 127 | * If the root of the collection is a page, then the main frame of the page 128 | * will be returned. 129 | * 130 | * @example this.nest(TextField, this.frame) 131 | */ 132 | public get frame(): Frame { 133 | return isLocator(this.root) 134 | ? // Playwright doesn't currently expose the frame of a locator as a 135 | // public API, so for now we need to get the private property. 136 | (this.root as unknown as { _frame: Frame })._frame 137 | : 'mainFrame' in this.root 138 | ? this.root.mainFrame() 139 | : this.root 140 | } 141 | 142 | /** 143 | * Returns the page that the collection is attached to. This can be used when 144 | * you need to access page methods inside your collection utility methods. For 145 | * example, if a utility needs to access `page.mouse`, this will allow that. 146 | * 147 | * @example this.page.mouse.down() 148 | */ 149 | public get page(): Page { 150 | return this.frame.page() 151 | } 152 | 153 | private getParent(frame: string | undefined, portal = false) { 154 | const root = portal ? this.frame : this.root 155 | return frame ? root.frameLocator(frame) : root 156 | } 157 | 158 | private enhanceMethod(method: T): Page[T] { 159 | const enhanced: EnhancedPageMethod = ( 160 | arg, 161 | { frame, portal, ...options } = {} 162 | ) => { 163 | return this.getParent(frame, portal)[method](arg as any, options) 164 | } 165 | 166 | return enhanced 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/enhance.ts: -------------------------------------------------------------------------------- 1 | import type { FrameLocator, Locator } from '@playwright/test' 2 | 3 | export type NestedCollection = T & { 4 | first(): T 5 | last(): T 6 | nth(index: number): T 7 | } 8 | 9 | export function enhance( 10 | collection: new (root: Locator | FrameLocator) => T, 11 | root: Locator | FrameLocator, 12 | instance: T 13 | ): NestedCollection { 14 | const inst = instance as NestedCollection 15 | 16 | inst.nth = (index: number) => new collection(root.nth(index)) 17 | inst.first = () => inst.nth(0) 18 | inst.last = () => inst.nth(-1) 19 | 20 | return inst 21 | } 22 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Collection } from './Collection.js' 2 | export type { SelectorOptions } from './Collection.js' 3 | export type { Handle } from './utils.js' 4 | export default Collection 5 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import type { Frame, FrameLocator, Locator, Page } from '@playwright/test' 2 | 3 | export type Handle = Page | Frame | FrameLocator | Locator 4 | 5 | export const isLocator = (handle: Handle): handle is Locator | FrameLocator => 6 | '_frame' in handle 7 | -------------------------------------------------------------------------------- /test/dynamic-selectors.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect, Page, test } from '@playwright/test' 2 | import Collection from '../src/index.js' 3 | 4 | class TodoPage extends Collection { 5 | item = (name: string) => this.el(`[data-name="${name}"]`) 6 | } 7 | 8 | test.describe('Dynamic selectors', () => { 9 | test('creates an element from a dynamic selector', async ({ page }) => { 10 | await page.setContent( 11 | '
  • One
  • Two
  • ' 12 | ) 13 | const todoPage = new TodoPage(page) 14 | await expect(todoPage.item('Ho')).toHaveText('Two') 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /test/elements.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect, Page, test } from '@playwright/test' 2 | import Collection from '../src/index.js' 3 | 4 | class RootPage extends Collection { 5 | inner = this.el('p') 6 | } 7 | 8 | test.describe('Elements', () => { 9 | test('provides access to the root element', async ({ page }) => { 10 | await page.setContent('

    One

    Two') 11 | const rootPage = new RootPage(page.locator('p')) 12 | await expect(rootPage.root).toHaveText('One') 13 | }) 14 | 15 | test('scopes elements inside the root element', async ({ page }) => { 16 | await page.setContent('

    Outer

    Inner

    ') 17 | const rootPage = new RootPage(page.locator('div')) 18 | await expect(rootPage.inner).toHaveText('Inner') 19 | }) 20 | 21 | test('can escape nesting using the portal option', async ({ page }) => { 22 | class ModalPage extends Collection { 23 | modal = this.el('#modal', { portal: true }) 24 | button = this.getByRole('button', { portal: true }) 25 | } 26 | 27 | await page.setContent(` 28 |
    29 | 30 | 31 | `) 32 | 33 | const modalPage = new ModalPage(page.locator('#content')) 34 | await expect(modalPage.modal).toHaveText('Hi') 35 | await expect(modalPage.button).toHaveText('foo') 36 | }) 37 | 38 | test('locates elements with specific text', async ({ page }) => { 39 | class TodoPage extends Collection { 40 | button = this.el('button', { hasText: 'Ho' }) 41 | } 42 | 43 | await page.setContent('') 44 | const todoPage = new TodoPage(page) 45 | await expect(todoPage.button).toHaveText('Ho') 46 | }) 47 | 48 | test('locates elements that contain a locator', async ({ page }) => { 49 | class TodoPage extends Collection { 50 | button = this.el('button', { has: this.el('span') }) 51 | } 52 | 53 | await page.setContent('') 54 | const todoPage = new TodoPage(page) 55 | await expect(todoPage.button).toHaveText('Hi') 56 | }) 57 | }) 58 | -------------------------------------------------------------------------------- /test/frame-locators.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect, FrameLocator, Page, test } from '@playwright/test' 2 | import Collection from '../src/index.js' 3 | 4 | test.describe.parallel('Frame locators', () => { 5 | test('accepts a frame locator as the root', async ({ page }) => { 6 | class ExamplePage extends Collection { 7 | header = this.el('h1') 8 | } 9 | 10 | await page.setContent(' 47 | 48 | 49 | `) 50 | const examplePage = new ExamplePage(page) 51 | const frame = examplePage.inner 52 | 53 | await expect(frame.first().header).toHaveText('Example Domain') 54 | await expect(frame.nth(1).header).toContainText('Playwright') 55 | await expect(frame.last().header).toHaveText('Quick Start') 56 | }) 57 | }) 58 | }) 59 | -------------------------------------------------------------------------------- /test/methods.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect, Page, test } from '@playwright/test' 2 | import Collection from '../src/index.js' 3 | 4 | class RootPage extends Collection { 5 | alt = this.getByAltText('my alt') 6 | label = this.getByLabel('my label') 7 | placeholder = this.getByPlaceholder('my placeholder') 8 | role = this.getByRole('button', { name: 'my role' }) 9 | testId = this.getByTestId('my-test-id') 10 | text = this.getByText('My text') 11 | title = this.getByTitle('My title') 12 | } 13 | 14 | test.describe('Testing library methods', () => { 15 | test('getByAltText', async ({ page }) => { 16 | await page.setContent(` 17 | foo 18 | my alt 19 | `) 20 | 21 | const rootPage = new RootPage(page) 22 | await expect(rootPage.alt).toHaveAttribute('id', 'yes') 23 | }) 24 | 25 | test('getByLabel', async ({ page }) => { 26 | await page.setContent(` 27 | 28 | 29 | 30 | 31 | `) 32 | 33 | const rootPage = new RootPage(page) 34 | await expect(rootPage.label).toHaveAttribute('id', 'yes') 35 | }) 36 | 37 | test('getByPlaceholder', async ({ page }) => { 38 | await page.setContent(` 39 | 40 | 41 | `) 42 | 43 | const rootPage = new RootPage(page) 44 | await expect(rootPage.placeholder).toHaveAttribute('id', 'yes') 45 | }) 46 | 47 | test('getByRole', async ({ page }) => { 48 | await page.setContent(` 49 | 50 | my role 51 |

    my role

    52 | `) 53 | 54 | const rootPage = new RootPage(page) 55 | await expect(rootPage.role).toHaveAttribute('id', 'yes') 56 | }) 57 | 58 | test('getByTestId', async ({ page }) => { 59 | await page.setContent(` 60 |

    yes

    61 |

    no

    62 | `) 63 | 64 | const rootPage = new RootPage(page) 65 | await expect(rootPage.testId).toHaveText('yes') 66 | }) 67 | 68 | test('getByText', async ({ page }) => { 69 | await page.setContent(` 70 |

    my text

    71 |

    other

    72 | `) 73 | 74 | const rootPage = new RootPage(page) 75 | await expect(rootPage.text).toHaveAttribute('id', 'yes') 76 | }) 77 | 78 | test('getByTitle', async ({ page }) => { 79 | await page.setContent(` 80 |

    no

    81 |

    yes

    82 | `) 83 | 84 | const rootPage = new RootPage(page) 85 | await expect(rootPage.title).toHaveText('yes') 86 | }) 87 | }) 88 | -------------------------------------------------------------------------------- /test/nested-collections.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | Frame, 4 | FrameLocator, 5 | Locator, 6 | Page, 7 | test, 8 | } from '@playwright/test' 9 | import Collection from '../src/index.js' 10 | 11 | class Child extends Collection { 12 | input = this.el('input') 13 | } 14 | 15 | test.describe('Nested collections', () => { 16 | test('locate child elements relative to the child root', async ({ page }) => { 17 | class Parent extends Collection { 18 | childLocator = this.nest(Child, this.el('#child')) 19 | childString = this.nest(Child, '#child') 20 | } 21 | 22 | await page.setContent( 23 | '
    ' 24 | ) 25 | 26 | const parent = new Parent(page) 27 | await expect(parent.childLocator.input).toHaveId('inner') 28 | await expect(parent.childLocator.input).toHaveCount(1) 29 | await expect(parent.childString.input).toHaveId('inner') 30 | await expect(parent.childString.input).toHaveCount(1) 31 | }) 32 | 33 | test('can use the parent root in the child', async ({ page }) => { 34 | class Parent extends Collection { 35 | child = this.nest(Child, this.root) 36 | } 37 | 38 | await page.setContent( 39 | '
    ' 40 | ) 41 | 42 | const parent = new Parent(page) 43 | await expect(parent.child.input).toHaveCount(2) 44 | }) 45 | 46 | test('can escape nesting using the frame property', async ({ page }) => { 47 | class Parent extends Collection { 48 | child = this.nest(Child, this.frame) 49 | } 50 | 51 | await page.setContent('
    ') 52 | const modalPage = new Parent(page.locator('#content')) 53 | await expect(modalPage.child.input).toHaveId('hi') 54 | }) 55 | }) 56 | -------------------------------------------------------------------------------- /test/nth.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect, Page, test } from '@playwright/test' 2 | import Collection from '../src/index.js' 3 | 4 | const content = ` 5 |
    Child One
    6 |
    Child Two
    7 |
    Child Three
    8 | ` 9 | 10 | class Child extends Collection { 11 | span = this.el('span') 12 | } 13 | 14 | class Parent extends Collection { 15 | child = this.nest(Child, 'div') 16 | } 17 | 18 | test.describe('nth', () => { 19 | test('can select the first, nth, and last of a collection', async ({ 20 | page, 21 | }) => { 22 | await page.setContent(content) 23 | const parent = new Parent(page) 24 | 25 | await expect(parent.child.first().root).toHaveText('Child One') 26 | await expect(parent.child.first().span).toHaveText('One') 27 | await expect(parent.child.nth(1).root).toHaveText('Child Two') 28 | await expect(parent.child.nth(1).span).toHaveText('Two') 29 | await expect(parent.child.last().root).toHaveText('Child Three') 30 | await expect(parent.child.last().span).toHaveText('Three') 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /test/utility-methods.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect, Page, test } from '@playwright/test' 2 | import Collection from '../src/index.js' 3 | 4 | class TodoPage extends Collection { 5 | button = this.el('"Click me"') 6 | 7 | async create() { 8 | await this.button.click() 9 | return this.button.isDisabled() 10 | } 11 | } 12 | 13 | test.describe('Utility methods', () => { 14 | test('can use elements inside utility methods', async ({ page }) => { 15 | await page.setContent('') 16 | const todoPage = new TodoPage(page) 17 | expect(await todoPage.create()).toBe(false) 18 | }) 19 | }) 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "nodenext", 4 | "moduleResolution": "nodenext", 5 | "target": "esnext", 6 | "strict": true, 7 | "skipLibCheck": true, 8 | "noEmit": true 9 | } 10 | } 11 | --------------------------------------------------------------------------------