junso-browser 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp.js +47 -11
- package/dist/server.js +6 -6
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var Pn=Object.create;var{getPrototypeOf:Tn,defineProperty:et,getOwnPropertyNames:jn}=Object;var Jn=Object.prototype.hasOwnProperty;function mn(t){return this[t]}var _n,Wn,zi=(t,n,i)=>{var c=t!=null&&typeof t==="object";if(c){var l=n?_n??=new WeakMap:Wn??=new WeakMap,s=l.get(t);if(s)return s}i=t!=null?Pn(Tn(t)):{};let f=n||!t||!t.__esModule?et(i,"default",{value:t,enumerable:!0}):i;for(let e of jn(t))if(!Jn.call(f,e))et(f,e,{get:mn.bind(t,e),enumerable:!0});if(c)l.set(t,f);return f};var Ki=(t,n)=>()=>(n||t((n={exports:{}}).exports,n),n.exports);var Xn=(t)=>t;function Gn(t,n){this[t]=Xn.bind(null,n)}var gi=(t,n)=>{for(var i in n)et(t,i,{get:n[i],enumerable:!0,configurable:!0,set:Gn.bind(n,i)})};var ot=(t,n,i)=>{return(c,l)=>{let s=-1;return f(0);async function f(e){if(e<=s)throw Error("next() called multiple times");s=e;let b,o=!1,r;if(t[e])r=t[e][0][0],c.req.routeIndex=e;else r=e===t.length&&l||void 0;if(r)try{b=await r(c,()=>f(e+1))}catch(x){if(x instanceof Error&&n)c.error=x,b=await n(x,c),o=!0;else throw x}else if(c.finalized===!1&&i)b=await i(c);if(b&&(c.finalized===!1||o))c.res=b;return c}}};var Xt=Symbol();var Gt=async(t,n=Object.create(null))=>{let{all:i=!1,dot:c=!1}=n,s=(t instanceof F?t.raw.headers:t.headers).get("Content-Type");if(s?.startsWith("multipart/form-data")||s?.startsWith("application/x-www-form-urlencoded"))return Qn(t,{all:i,dot:c});return{}};async function Qn(t,n){let i=await t.formData();if(i)return Yn(i,n);return{}}function Yn(t,n){let i=Object.create(null);if(t.forEach((c,l)=>{if(!(n.all||l.endsWith("[]")))i[l]=c;else Vn(i,l,c)}),n.dot)Object.entries(i).forEach(([c,l])=>{if(c.includes("."))wn(i,c,l),delete i[c]});return i}var Vn=(t,n,i)=>{if(t[n]!==void 0)if(Array.isArray(t[n]))t[n].push(i);else t[n]=[t[n],i];else if(!n.endsWith("[]"))t[n]=i;else t[n]=[i]},wn=(t,n,i)=>{if(/(?:^|\.)__proto__\./.test(n))return;let c=t,l=n.split(".");l.forEach((s,f)=>{if(f===l.length-1)c[s]=i;else{if(!c[s]||typeof c[s]!=="object"||Array.isArray(c[s])||c[s]instanceof File)c[s]=Object.create(null);c=c[s]}})};var xt=(t)=>{let n=t.split("/");if(n[0]==="")n.shift();return n},Qt=(t)=>{let{groups:n,path:i}=An(t),c=xt(i);return Zn(c,n)},An=(t)=>{let n=[];return t=t.replace(/\{[^}]+\}/g,(i,c)=>{let l=`@${c}`;return n.push([l,i]),l}),{groups:n,path:t}},Zn=(t,n)=>{for(let i=n.length-1;i>=0;i--){let[c]=n[i];for(let l=t.length-1;l>=0;l--)if(t[l].includes(c)){t[l]=t[l].replace(c,n[i][1]);break}}return t},D={},Yt=(t,n)=>{if(t==="*")return"*";let i=t.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);if(i){let c=`${t}#${n}`;if(!D[c])if(i[2])D[c]=n&&n[0]!==":"&&n[0]!=="*"?[c,i[1],new RegExp(`^${i[2]}(?=/${n})`)]:[t,i[1],new RegExp(`^${i[2]}$`)];else D[c]=[t,i[1],!0];return D[c]}return null},C=(t,n)=>{try{return n(t)}catch{return t.replace(/(?:%[0-9A-Fa-f]{2})+/g,(i)=>{try{return n(i)}catch{return i}})}},Mn=(t)=>C(t,decodeURI),ut=(t)=>{let n=t.url,i=n.indexOf("/",n.indexOf(":")+4),c=i;for(;c<n.length;c++){let l=n.charCodeAt(c);if(l===37){let s=n.indexOf("?",c),f=n.indexOf("#",c),e=s===-1?f===-1?void 0:f:f===-1?s:Math.min(s,f),b=n.slice(i,e);return Mn(b.includes("%25")?b.replace(/%25/g,"%2525"):b)}else if(l===63||l===35)break}return n.slice(i,c)};var Vt=(t)=>{let n=ut(t);return n.length>1&&n.at(-1)==="/"?n.slice(0,-1):n},g=(t,n,...i)=>{if(i.length)n=g(n,...i);return`${t?.[0]==="/"?"":"/"}${t}${n==="/"?"":`${t?.at(-1)==="/"?"":"/"}${n?.[0]==="/"?n.slice(1):n}`}`},H=(t)=>{if(t.charCodeAt(t.length-1)!==63||!t.includes(":"))return null;let n=t.split("/"),i=[],c="";return n.forEach((l)=>{if(l!==""&&!/\:/.test(l))c+="/"+l;else if(/\:/.test(l))if(/\?/.test(l)){if(i.length===0&&c==="")i.push("/");else i.push(c);let s=l.replace("?","");c+="/"+s,i.push(c)}else c+="/"+l}),i.filter((l,s,f)=>f.indexOf(l)===s)},rt=(t)=>{if(!/[%+]/.test(t))return t;if(t.indexOf("+")!==-1)t=t.replace(/\+/g," ");return t.indexOf("%")!==-1?C(t,dt):t},wt=(t,n,i)=>{let c;if(!i&&n&&!/[%+]/.test(n)){let f=t.indexOf("?",8);if(f===-1)return;if(!t.startsWith(n,f+1))f=t.indexOf(`&${n}`,f+1);while(f!==-1){let e=t.charCodeAt(f+n.length+1);if(e===61){let b=f+n.length+2,o=t.indexOf("&",b);return rt(t.slice(b,o===-1?void 0:o))}else if(e==38||isNaN(e))return"";f=t.indexOf(`&${n}`,f+1)}if(c=/[%+]/.test(t),!c)return}let l={};c??=/[%+]/.test(t);let s=t.indexOf("?",8);while(s!==-1){let f=t.indexOf("&",s+1),e=t.indexOf("=",s);if(e>f&&f!==-1)e=-1;let b=t.slice(s+1,e===-1?f===-1?void 0:f:e);if(c)b=rt(b);if(s=f,b==="")continue;let o;if(e===-1)o="";else if(o=t.slice(e+1,f===-1?void 0:f),c)o=rt(o);if(i){if(!(l[b]&&Array.isArray(l[b])))l[b]=[];l[b].push(o)}else l[b]??=o}return n?l[n]:l},At=wt,Zt=(t,n)=>{return wt(t,n,!0)},dt=decodeURIComponent;var Mt=(t)=>C(t,dt),F=class{raw;#t;#n;routeIndex=0;path;bodyCache={};constructor(t,n="/",i=[[]]){this.raw=t,this.path=n,this.#n=i,this.#t={}}param(t){return t?this.#i(t):this.#s()}#i(t){let n=this.#n[0][this.routeIndex][1][t],i=this.#l(n);return i&&/\%/.test(i)?Mt(i):i}#s(){let t={},n=Object.keys(this.#n[0][this.routeIndex][1]);for(let i of n){let c=this.#l(this.#n[0][this.routeIndex][1][i]);if(c!==void 0)t[i]=/\%/.test(c)?Mt(c):c}return t}#l(t){return this.#n[1]?this.#n[1][t]:t}query(t){return At(this.url,t)}queries(t){return Zt(this.url,t)}header(t){if(t)return this.raw.headers.get(t)??void 0;let n={};return this.raw.headers.forEach((i,c)=>{n[c]=i}),n}async parseBody(t){return Gt(this,t)}#c=(t)=>{let{bodyCache:n,raw:i}=this,c=n[t];if(c)return c;let l=Object.keys(n)[0];if(l)return n[l].then((s)=>{if(l==="json")s=JSON.stringify(s);return new Response(s)[t]()});return n[t]=i[t]()};json(){return this.#c("text").then((t)=>JSON.parse(t))}text(){return this.#c("text")}arrayBuffer(){return this.#c("arrayBuffer")}bytes(){return this.#c("arrayBuffer").then((t)=>new Uint8Array(t))}blob(){return this.#c("blob")}formData(){return this.#c("formData")}addValidatedData(t,n){this.#t[t]=n}valid(t){return this.#t[t]}get url(){return this.raw.url}get method(){return this.raw.method}get[Xt](){return this.#n}get matchedRoutes(){return this.#n[0].map(([[,t]])=>t)}get routePath(){return this.#n[0].map(([[,t]])=>t)[this.routeIndex].path}};var It={Stringify:1,BeforeStream:2,Stream:3},In=(t,n)=>{let i=new String(t);return i.isEscaped=!0,i.callbacks=n,i};var Et=async(t,n,i,c,l)=>{if(typeof t==="object"&&!(t instanceof String)){if(!(t instanceof Promise))t=t.toString();if(t instanceof Promise)t=await t}let s=t.callbacks;if(!s?.length)return Promise.resolve(t);if(l)l[0]+=t;else l=[t];let f=Promise.all(s.map((e)=>e({phase:n,buffer:l,context:c}))).then((e)=>Promise.all(e.filter(Boolean).map((b)=>Et(b,n,!1,c,l))).then(()=>l[0]));if(i)return In(await f,s);else return f};var Un="text/plain; charset=UTF-8",Ot=(t,n)=>{return{"Content-Type":t,...n}},Y=(t,n)=>new Response(t,n),yt=class{#t;#n;env={};#i;finalized=!1;error;#s;#l;#c;#r;#e;#o;#b;#x;#u;constructor(t,n){if(this.#t=t,n)this.#l=n.executionCtx,this.env=n.env,this.#o=n.notFoundHandler,this.#u=n.path,this.#x=n.matchResult}get req(){return this.#n??=new F(this.#t,this.#u,this.#x),this.#n}get event(){if(this.#l&&"respondWith"in this.#l)return this.#l;else throw Error("This context has no FetchEvent")}get executionCtx(){if(this.#l)return this.#l;else throw Error("This context has no ExecutionContext")}get res(){return this.#c||=Y(null,{headers:this.#b??=new Headers})}set res(t){if(this.#c&&t){t=Y(t.body,t);for(let[n,i]of this.#c.headers.entries()){if(n==="content-type")continue;if(n==="set-cookie"){let c=this.#c.headers.getSetCookie();t.headers.delete("set-cookie");for(let l of c)t.headers.append("set-cookie",l)}else t.headers.set(n,i)}}this.#c=t,this.finalized=!0}render=(...t)=>{return this.#e??=(n)=>this.html(n),this.#e(...t)};setLayout=(t)=>this.#r=t;getLayout=()=>this.#r;setRenderer=(t)=>{this.#e=t};header=(t,n,i)=>{if(this.finalized)this.#c=Y(this.#c.body,this.#c);let c=this.#c?this.#c.headers:this.#b??=new Headers;if(n===void 0)c.delete(t);else if(i?.append)c.append(t,n);else c.set(t,n)};status=(t)=>{this.#s=t};set=(t,n)=>{this.#i??=new Map,this.#i.set(t,n)};get=(t)=>{return this.#i?this.#i.get(t):void 0};get var(){if(!this.#i)return{};return Object.fromEntries(this.#i)}#f(t,n,i){let c=this.#c?new Headers(this.#c.headers):this.#b??new Headers;if(typeof n==="object"&&"headers"in n){let s=n.headers instanceof Headers?n.headers:new Headers(n.headers);for(let[f,e]of s)if(f.toLowerCase()==="set-cookie")c.append(f,e);else c.set(f,e)}if(i)for(let[s,f]of Object.entries(i))if(typeof f==="string")c.set(s,f);else{c.delete(s);for(let e of f)c.append(s,e)}let l=typeof n==="number"?n:n?.status??this.#s;return Y(t,{status:l,headers:c})}newResponse=(...t)=>this.#f(...t);body=(t,n,i)=>this.#f(t,n,i);text=(t,n,i)=>{return!this.#b&&!this.#s&&!n&&!i&&!this.finalized?new Response(t):this.#f(t,n,Ot(Un,i))};json=(t,n,i)=>{return this.#f(JSON.stringify(t),n,Ot("application/json",i))};html=(t,n,i)=>{let c=(l)=>this.#f(l,n,Ot("text/html; charset=UTF-8",i));return typeof t==="object"?Et(t,It.Stringify,!1,{}).then(c):c(t)};redirect=(t,n)=>{let i=String(t);return this.header("Location",!/[^\x00-\xFF]/.test(i)?i:encodeURI(i)),this.newResponse(null,n??302)};notFound=()=>{return this.#o??=()=>Y(),this.#o(this)}};var d="ALL",Ut="all",Rt=["get","post","put","delete","options","patch"],p="Can not add a route since the matcher is already built.",h=class extends Error{};var kt="__COMPOSED_HANDLER";var Rn=(t)=>{return t.text("404 Not Found",404)},Ft=(t,n)=>{if("getResponse"in t){let i=t.getResponse();return n.newResponse(i.body,i)}return console.error(t),n.text("Internal Server Error",500)},Dt=class t{get;post;put;delete;options;patch;all;on;use;router;getPath;_basePath="/";#t="/";routes=[];constructor(n={}){[...Rt,Ut].forEach((s)=>{this[s]=(f,...e)=>{if(typeof f==="string")this.#t=f;else this.#s(s,this.#t,f);return e.forEach((b)=>{this.#s(s,this.#t,b)}),this}}),this.on=(s,f,...e)=>{for(let b of[f].flat()){this.#t=b;for(let o of[s].flat())e.map((r)=>{this.#s(o.toUpperCase(),this.#t,r)})}return this},this.use=(s,...f)=>{if(typeof s==="string")this.#t=s;else this.#t="*",f.unshift(s);return f.forEach((e)=>{this.#s(d,this.#t,e)}),this};let{strict:c,...l}=n;Object.assign(this,l),this.getPath=c??!0?n.getPath??ut:Vt}#n(){let n=new t({router:this.router,getPath:this.getPath});return n.errorHandler=this.errorHandler,n.#i=this.#i,n.routes=this.routes,n}#i=Rn;errorHandler=Ft;route(n,i){let c=this.basePath(n);return i.routes.map((l)=>{let s;if(i.errorHandler===Ft)s=l.handler;else s=async(f,e)=>(await ot([],i.errorHandler)(f,()=>l.handler(f,e))).res,s[kt]=l.handler;c.#s(l.method,l.path,s,l.basePath)}),this}basePath(n){let i=this.#n();return i._basePath=g(this._basePath,n),i}onError=(n)=>{return this.errorHandler=n,this};notFound=(n)=>{return this.#i=n,this};mount(n,i,c){let l,s;if(c)if(typeof c==="function")s=c;else if(s=c.optionHandler,c.replaceRequest===!1)l=(b)=>b;else l=c.replaceRequest;let f=s?(b)=>{let o=s(b);return Array.isArray(o)?o:[o]}:(b)=>{let o=void 0;try{o=b.executionCtx}catch{}return[b.env,o]};l||=(()=>{let b=g(this._basePath,n),o=b==="/"?0:b.length;return(r)=>{let x=new URL(r.url);return x.pathname=this.getPath(r).slice(o)||"/",new Request(x,r)}})();let e=async(b,o)=>{let r=await i(l(b.req.raw),...f(b));if(r)return r;await o()};return this.#s(d,g(n,"*"),e),this}#s(n,i,c,l){n=n.toUpperCase(),i=g(this._basePath,i);let s={basePath:l!==void 0?g(this._basePath,l):this._basePath,path:i,method:n,handler:c};this.router.add(n,i,[c,s]),this.routes.push(s)}#l(n,i){if(n instanceof Error)return this.errorHandler(n,i);throw n}#c(n,i,c,l){if(l==="HEAD")return(async()=>new Response(null,await this.#c(n,i,c,"GET")))();let s=this.getPath(n,{env:c}),f=this.router.match(l,s),e=new yt(n,{path:s,matchResult:f,env:c,executionCtx:i,notFoundHandler:this.#i});if(f[0].length===1){let o;try{o=f[0][0][0][0](e,async()=>{e.res=await this.#i(e)})}catch(r){return this.#l(r,e)}return o instanceof Promise?o.then((r)=>r||(e.finalized?e.res:this.#i(e))).catch((r)=>this.#l(r,e)):o??this.#i(e)}let b=ot(f[0],this.errorHandler,this.#i);return(async()=>{try{let o=await b(e);if(!o.finalized)throw Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return o.res}catch(o){return this.#l(o,e)}})()}fetch=(n,...i)=>{return this.#c(n,i[1],i[0],n.method)};request=(n,i,c,l)=>{if(n instanceof Request)return this.fetch(i?new Request(n,i):n,c,l);return n=n.toString(),this.fetch(new Request(/^https?:\/\//.test(n)?n:`http://localhost${g("/",n)}`,i),c,l)};fire=()=>{addEventListener("fetch",(n)=>{n.respondWith(this.#c(n.request,n,void 0,n.request.method))})}};var V=[];function q(t,n){let i=this.buildAllMatchers(),c=(l,s)=>{let f=i[l]||i[d],e=f[2][s];if(e)return e;let b=s.match(f[0]);if(!b)return[[],V];let o=b.indexOf("",1);return[f[1][o],b]};return this.match=c,c(t,n)}var tt="[^/]+",w=".*",A="(?:|/.*)",P=Symbol(),kn=new Set(".\\+*[^]$()");function Fn(t,n){if(t.length===1)return n.length===1?t<n?-1:1:-1;if(n.length===1)return 1;if(t===w||t===A)return 1;else if(n===w||n===A)return-1;if(t===tt)return 1;else if(n===tt)return-1;return t.length===n.length?t<n?-1:1:n.length-t.length}var Ct=class t{#t;#n;#i=Object.create(null);insert(n,i,c,l,s){if(n.length===0){if(this.#t!==void 0)throw P;if(s)return;this.#t=i;return}let[f,...e]=n,b=f==="*"?e.length===0?["","",w]:["","",tt]:f==="/*"?["","",A]:f.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/),o;if(b){let r=b[1],x=b[2]||tt;if(r&&b[2]){if(x===".*")throw P;if(x=x.replace(/^\((?!\?:)(?=[^)]+\)$)/,"(?:"),/\((?!\?:)/.test(x))throw P}if(o=this.#i[x],!o){if(Object.keys(this.#i).some((E)=>E!==w&&E!==A))throw P;if(s)return;if(o=this.#i[x]=new t,r!=="")o.#n=l.varIndex++}if(!s&&r!=="")c.push([r,o.#n])}else if(o=this.#i[f],!o){if(Object.keys(this.#i).some((r)=>r.length>1&&r!==w&&r!==A))throw P;if(s)return;o=this.#i[f]=new t}o.insert(e,i,c,l,s)}buildRegExpStr(){let i=Object.keys(this.#i).sort(Fn).map((c)=>{let l=this.#i[c];return(typeof l.#n==="number"?`(${c})@${l.#n}`:kn.has(c)?`\\${c}`:c)+l.buildRegExpStr()});if(typeof this.#t==="number")i.unshift(`#${this.#t}`);if(i.length===0)return"";if(i.length===1)return i[0];return"(?:"+i.join("|")+")"}};var Ht=class{#t={varIndex:0};#n=new Ct;insert(t,n,i){let c=[],l=[];for(let f=0;;){let e=!1;if(t=t.replace(/\{[^}]+\}/g,(b)=>{let o=`@\\${f}`;return l[f]=[o,b],f++,e=!0,o}),!e)break}let s=t.match(/(?::[^\/]+)|(?:\/\*$)|./g)||[];for(let f=l.length-1;f>=0;f--){let[e]=l[f];for(let b=s.length-1;b>=0;b--)if(s[b].indexOf(e)!==-1){s[b]=s[b].replace(e,l[f][1]);break}}return this.#n.insert(s,n,c,this.#t,i),c}buildRegExp(){let t=this.#n.buildRegExpStr();if(t==="")return[/^$/,[],[]];let n=0,i=[],c=[];return t=t.replace(/#(\d+)|@(\d+)|\.\*\$/g,(l,s,f)=>{if(s!==void 0)return i[++n]=Number(s),"$()";if(f!==void 0)return c[Number(f)]=++n,"";return""}),[new RegExp(`^${t}`),i,c]}};var Dn=[/^$/,[],Object.create(null)],pt=Object.create(null);function ht(t){return pt[t]??=new RegExp(t==="*"?"":`^${t.replace(/\/\*$|([.\\+*[^\]$()])/g,(n,i)=>i?`\\${i}`:"(?:|/.*)")}$`)}function Cn(){pt=Object.create(null)}function Hn(t){let n=new Ht,i=[];if(t.length===0)return Dn;let c=t.map((o)=>[!/\*|\/:/.test(o[0]),...o]).sort(([o,r],[x,E])=>o?1:x?-1:r.length-E.length),l=Object.create(null);for(let o=0,r=-1,x=c.length;o<x;o++){let[E,O,$]=c[o];if(E)l[O]=[$.map(([a])=>[a,Object.create(null)]),V];else r++;let v;try{v=n.insert(O,r,E)}catch(a){throw a===P?new h(O):a}if(E)continue;i[r]=$.map(([a,y])=>{let B=Object.create(null);y-=1;for(;y>=0;y--){let[X,ft]=v[y];B[X]=ft}return[a,B]})}let[s,f,e]=n.buildRegExp();for(let o=0,r=i.length;o<r;o++)for(let x=0,E=i[o].length;x<E;x++){let O=i[o][x]?.[1];if(!O)continue;let $=Object.keys(O);for(let v=0,a=$.length;v<a;v++)O[$[v]]=e[O[$[v]]]}let b=[];for(let o in f)b[o]=i[f[o]];return[s,b,l]}function J(t,n){if(!t)return;for(let i of Object.keys(t).sort((c,l)=>l.length-c.length))if(ht(i).test(n))return[...t[i]];return}var nt=class{name="RegExpRouter";#t;#n;constructor(){this.#t={[d]:Object.create(null)},this.#n={[d]:Object.create(null)}}add(t,n,i){let c=this.#t,l=this.#n;if(!c||!l)throw Error(p);if(!c[t])[c,l].forEach((e)=>{e[t]=Object.create(null),Object.keys(e[d]).forEach((b)=>{e[t][b]=[...e[d][b]]})});if(n==="/*")n="*";let s=(n.match(/\/:/g)||[]).length;if(/\*$/.test(n)){let e=ht(n);if(t===d)Object.keys(c).forEach((b)=>{c[b][n]||=J(c[b],n)||J(c[d],n)||[]});else c[t][n]||=J(c[t],n)||J(c[d],n)||[];Object.keys(c).forEach((b)=>{if(t===d||t===b)Object.keys(c[b]).forEach((o)=>{e.test(o)&&c[b][o].push([i,s])})}),Object.keys(l).forEach((b)=>{if(t===d||t===b)Object.keys(l[b]).forEach((o)=>e.test(o)&&l[b][o].push([i,s]))});return}let f=H(n)||[n];for(let e=0,b=f.length;e<b;e++){let o=f[e];Object.keys(l).forEach((r)=>{if(t===d||t===r)l[r][o]||=[...J(c[r],o)||J(c[d],o)||[]],l[r][o].push([i,s-b+e+1])})}}match=q;buildAllMatchers(){let t=Object.create(null);return Object.keys(this.#n).concat(Object.keys(this.#t)).forEach((n)=>{t[n]||=this.#i(n)}),this.#t=this.#n=void 0,Cn(),t}#i(t){let n=[],i=t===d;if([this.#t,this.#n].forEach((c)=>{let l=c[t]?Object.keys(c[t]).map((s)=>[s,c[t][s]]):[];if(l.length!==0)i||=!0,n.push(...l);else if(t!==d)n.push(...Object.keys(c[d]).map((s)=>[s,c[d][s]]))}),!i)return null;else return Hn(n)}};var pn=class{name="PreparedRegExpRouter";#t;#n;constructor(t,n){this.#t=t,this.#n=n}#i(t,n){let i=this.#t[t];i[1].forEach((c)=>c&&c.push(n)),Object.values(i[2]).forEach((c)=>c[0].push(n))}#s(t,n,i,c,l){let s=this.#t[t];if(!l)s[2][n][0].push([i,{}]);else c.forEach((f)=>{if(typeof f==="number")s[1][f].push([i,l]);else s[2][f||n][0].push([i,l])})}add(t,n,i){if(!this.#t[t]){let l=this.#t[d],s={};for(let f in l[2])s[f]=[l[2][f][0].slice(),V];this.#t[t]=[l[0],l[1].map((f)=>Array.isArray(f)?f.slice():0),s]}if(n==="/*"||n==="*"){let l=[i,{}];if(t===d)for(let s in this.#t)this.#i(s,l);else this.#i(t,l);return}let c=this.#n[n];if(!c)throw Error(`Path ${n} is not registered`);for(let[l,s]of c)if(t===d)for(let f in this.#t)this.#s(f,n,i,l,s);else this.#s(t,n,i,l,s)}buildAllMatchers(){return this.#t}match=q};var Nt=class{name="SmartRouter";#t=[];#n=[];constructor(t){this.#t=t.routers}add(t,n,i){if(!this.#n)throw Error(p);this.#n.push([t,n,i])}match(t,n){if(!this.#n)throw Error("Fatal error");let i=this.#t,c=this.#n,l=i.length,s=0,f;for(;s<l;s++){let e=i[s];try{for(let b=0,o=c.length;b<o;b++)e.add(...c[b]);f=e.match(t,n)}catch(b){if(b instanceof h)continue;throw b}this.match=e.match.bind(e),this.#t=[e],this.#n=void 0;break}if(s===l)throw Error("Fatal error");return this.name=`SmartRouter + ${this.activeRouter.name}`,f}get activeRouter(){if(this.#n||this.#t.length!==1)throw Error("No active router has been determined yet.");return this.#t[0]}};var Z=Object.create(null),hn=(t)=>{for(let n in t)return!0;return!1},qt=class t{#t;#n;#i;#s=0;#l=Z;constructor(n,i,c){if(this.#n=c||Object.create(null),this.#t=[],n&&i){let l=Object.create(null);l[n]={handler:i,possibleKeys:[],score:0},this.#t=[l]}this.#i=[]}insert(n,i,c){this.#s=++this.#s;let l=this,s=Qt(i),f=[];for(let e=0,b=s.length;e<b;e++){let o=s[e],r=s[e+1],x=Yt(o,r),E=Array.isArray(x)?x[0]:o;if(E in l.#n){if(l=l.#n[E],x)f.push(x[1]);continue}if(l.#n[E]=new t,x)l.#i.push(x),f.push(x[1]);l=l.#n[E]}return l.#t.push({[n]:{handler:c,possibleKeys:f.filter((e,b,o)=>o.indexOf(e)===b),score:this.#s}}),l}#c(n,i,c,l,s){for(let f=0,e=i.#t.length;f<e;f++){let b=i.#t[f],o=b[c]||b[d],r={};if(o!==void 0){if(o.params=Object.create(null),n.push(o),l!==Z||s&&s!==Z)for(let x=0,E=o.possibleKeys.length;x<E;x++){let O=o.possibleKeys[x],$=r[o.score];o.params[O]=s?.[O]&&!$?s[O]:l[O]??s?.[O],r[o.score]=!0}}}}search(n,i){let c=[];this.#l=Z;let s=[this],f=xt(i),e=[],b=f.length,o=null;for(let r=0;r<b;r++){let x=f[r],E=r===b-1,O=[];for(let v=0,a=s.length;v<a;v++){let y=s[v],B=y.#n[x];if(B)if(B.#l=y.#l,E){if(B.#n["*"])this.#c(c,B.#n["*"],n,y.#l);this.#c(c,B,n,y.#l)}else O.push(B);for(let X=0,ft=y.#i.length;X<ft;X++){let _t=y.#i[X],K=y.#l===Z?{}:{...y.#l};if(_t==="*"){let j=y.#n["*"];if(j)this.#c(c,j,n,y.#l),j.#l=K,O.push(j);continue}let[gn,Wt,G]=_t;if(!x&&!(G instanceof RegExp))continue;let L=y.#n[gn];if(G instanceof RegExp){if(o===null){o=Array(b);let k=i[0]==="/"?1:0;for(let Q=0;Q<b;Q++)o[Q]=k,k+=f[Q].length+1}let j=i.substring(o[r]),bt=G.exec(j);if(bt){if(K[Wt]=bt[0],this.#c(c,L,n,y.#l,K),hn(L.#n)){L.#l=K;let k=bt[0].match(/\//)?.length??0;(e[k]||=[]).push(L)}continue}}if(G===!0||G.test(x))if(K[Wt]=x,E){if(this.#c(c,L,n,K,y.#l),L.#n["*"])this.#c(c,L.#n["*"],n,K,y.#l)}else L.#l=K,O.push(L)}}let $=e.shift();s=$?O.concat($):O}if(c.length>1)c.sort((r,x)=>{return r.score-x.score});return[c.map(({handler:r,params:x})=>[r,x])]}};var St=class{name="TrieRouter";#t;constructor(){this.#t=new qt}add(t,n,i){let c=H(n);if(c){for(let l=0,s=c.length;l<s;l++)this.#t.insert(t,c[l],i);return}this.#t.insert(t,n,i)}match(t,n){return this.#t.search(t,n)}};var $t=class extends Dt{constructor(t={}){super(t);this.router=t.router??new Nt({routers:[new nt,new St]})}};import qn from"os";import vt from"path";var u={port:Number(process.env.JUNSO_BROWSER_PORT??8790),host:process.env.JUNSO_BROWSER_HOST??"127.0.0.1",token:process.env.JUNSO_BROWSER_TOKEN??"",dataDir:process.env.JUNSO_BROWSER_DATA_DIR??vt.join(qn.homedir(),".junso-browser"),maxInstances:Number(process.env.JUNSO_BROWSER_MAX_INSTANCES??3),idleReapMs:Number(process.env.JUNSO_BROWSER_IDLE_MS??1800000),cloakPath:process.env.JUNSO_BROWSER_CLOAK_PATH,publicUrl:process.env.JUNSO_BROWSER_PUBLIC_URL};function at(){return vt.join(u.dataDir,"profiles.json")}function it(t){return vt.join(u.dataDir,"profiles",t,"user-data")}function ct(){return u.host==="127.0.0.1"||u.host==="localhost"||u.host==="::1"}import{mkdir as ci,readFile as li,writeFile as si,rm as fi}from"fs/promises";import bi from"path";import{randomUUID as ei}from"crypto";import ti from"os";import Lt from"path";import{existsSync as tn,readdirSync as ni}from"fs";function m(){if(u.cloakPath&&tn(u.cloakPath))return u.cloakPath;let t=Lt.join(ti.homedir(),".cloakbrowser"),n;try{n=ni(t).filter((c)=>c.startsWith("chromium-"))}catch{return null}n.sort().reverse();let i=process.platform==="win32"?"chrome.exe":"chrome";for(let c of n){let l=Lt.join(t,c,i);if(tn(l))return l}return null}var Bt=!1;function nn(){if(Bt)return;if(process.env.JUNSO_BROWSER_NO_CLOAK_DOWNLOAD==="true")return;if(m())return;Bt=!0,console.log("[junso-browser] CloakBrowser binary not found \u2014 downloading in background\u2026");let t=Lt.resolve(import.meta.dir,"..");Bun.spawn([process.execPath,"x","cloakbrowser","install"],{cwd:t,stdout:"inherit",stderr:"inherit"}).exited.then((i)=>{Bt=!1,console.log(i===0?"[junso-browser] CloakBrowser ready.":`[junso-browser] cloak download exited ${i}.`)})}function ii(t){try{let n=new URL(t);return`${n.protocol}//${n.host}`}catch{return t}}function cn(t){if(!t)return null;try{let n=new URL(t);if(!n.username)return null;return{username:decodeURIComponent(n.username),password:decodeURIComponent(n.password)}}catch{return null}}function zt(){return Math.floor(Math.random()*90000)+1e4}function ln(t,n,i){let c=t.fingerprint,l=["--no-sandbox",`--fingerprint=${c.seed}`,`--fingerprint-platform=${c.platform??"windows"}`];if(c.timezone)l.push(`--fingerprint-timezone=${c.timezone}`);if(c.locale)l.push(`--fingerprint-locale=${c.locale}`,`--accept-lang=${c.locale}`);if(t.proxy)l.push(`--proxy-server=${ii(t.proxy)}`);return l.push(`--user-data-dir=${i}`,`--remote-debugging-port=${n}`,"--remote-debugging-address=127.0.0.1","--headless=new"),l}function sn(t){let n={...process.env};if(t.fingerprint.timezone)n.TZ=t.fingerprint.timezone;return n}var _=null,fn=Promise.resolve();async function M(){if(_)return _;try{let t=await li(at(),"utf8"),n=JSON.parse(t);_=n&&typeof n==="object"?n:{}}catch{_={}}return _}async function Kt(t){await ci(u.dataDir,{recursive:!0}),await si(at(),JSON.stringify(t,null,2)+`
|
|
3
|
-
`,"utf8"),
|
|
4
|
-
`),
|
|
2
|
+
var Tn=Object.create;var{getPrototypeOf:_n,defineProperty:ot,getOwnPropertyNames:an}=Object;var Xn=Object.prototype.hasOwnProperty;function Gn(t){return this[t]}var Qn,Yn,ji=(t,n,i)=>{var c=t!=null&&typeof t==="object";if(c){var l=n?Qn??=new WeakMap:Yn??=new WeakMap,f=l.get(t);if(f)return f}i=t!=null?Tn(_n(t)):{};let b=n||!t||!t.__esModule?ot(i,"default",{value:t,enumerable:!0}):i;for(let o of an(t))if(!Xn.call(b,o))ot(b,o,{get:Gn.bind(t,o),enumerable:!0});if(c)l.set(t,b);return b};var Pi=(t,n)=>()=>(n||t((n={exports:{}}).exports,n),n.exports);var Wn=(t)=>t;function Vn(t,n){this[t]=Wn.bind(null,n)}var Ji=(t,n)=>{for(var i in n)ot(t,i,{get:n[i],enumerable:!0,configurable:!0,set:Vn.bind(n,i)})};var xt=(t,n,i)=>{return(c,l)=>{let f=-1;return b(0);async function b(o){if(o<=f)throw Error("next() called multiple times");f=o;let s,x=!1,e;if(t[o])e=t[o][0][0],c.req.routeIndex=o;else e=o===t.length&&l||void 0;if(e)try{s=await e(c,()=>b(o+1))}catch(u){if(u instanceof Error&&n)c.error=u,s=await n(u,c),x=!0;else throw u}else if(c.finalized===!1&&i)s=await i(c);if(s&&(c.finalized===!1||x))c.res=s;return c}}};var Yt=Symbol();var Wt=async(t,n=Object.create(null))=>{let{all:i=!1,dot:c=!1}=n,f=(t instanceof I?t.raw.headers:t.headers).get("Content-Type");if(f?.startsWith("multipart/form-data")||f?.startsWith("application/x-www-form-urlencoded"))return gn(t,{all:i,dot:c});return{}};async function gn(t,n){let i=await t.formData();if(i)return An(i,n);return{}}function An(t,n){let i=Object.create(null);if(t.forEach((c,l)=>{if(!(n.all||l.endsWith("[]")))i[l]=c;else Zn(i,l,c)}),n.dot)Object.entries(i).forEach(([c,l])=>{if(c.includes("."))Mn(i,c,l),delete i[c]});return i}var Zn=(t,n,i)=>{if(t[n]!==void 0)if(Array.isArray(t[n]))t[n].push(i);else t[n]=[t[n],i];else if(!n.endsWith("[]"))t[n]=i;else t[n]=[i]},Mn=(t,n,i)=>{if(/(?:^|\.)__proto__\./.test(n))return;let c=t,l=n.split(".");l.forEach((f,b)=>{if(b===l.length-1)c[f]=i;else{if(!c[f]||typeof c[f]!=="object"||Array.isArray(c[f])||c[f]instanceof File)c[f]=Object.create(null);c=c[f]}})};var ut=(t)=>{let n=t.split("/");if(n[0]==="")n.shift();return n},Vt=(t)=>{let{groups:n,path:i}=Un(t),c=ut(i);return mn(c,n)},Un=(t)=>{let n=[];return t=t.replace(/\{[^}]+\}/g,(i,c)=>{let l=`@${c}`;return n.push([l,i]),l}),{groups:n,path:t}},mn=(t,n)=>{for(let i=n.length-1;i>=0;i--){let[c]=n[i];for(let l=t.length-1;l>=0;l--)if(t[l].includes(c)){t[l]=t[l].replace(c,n[i][1]);break}}return t},C={},gt=(t,n)=>{if(t==="*")return"*";let i=t.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);if(i){let c=`${t}#${n}`;if(!C[c])if(i[2])C[c]=n&&n[0]!==":"&&n[0]!=="*"?[c,i[1],new RegExp(`^${i[2]}(?=/${n})`)]:[t,i[1],new RegExp(`^${i[2]}$`)];else C[c]=[t,i[1],!0];return C[c]}return null},H=(t,n)=>{try{return n(t)}catch{return t.replace(/(?:%[0-9A-Fa-f]{2})+/g,(i)=>{try{return n(i)}catch{return i}})}},Rn=(t)=>H(t,decodeURI),Et=(t)=>{let n=t.url,i=n.indexOf("/",n.indexOf(":")+4),c=i;for(;c<n.length;c++){let l=n.charCodeAt(c);if(l===37){let f=n.indexOf("?",c),b=n.indexOf("#",c),o=f===-1?b===-1?void 0:b:b===-1?f:Math.min(f,b),s=n.slice(i,o);return Rn(s.includes("%25")?s.replace(/%25/g,"%2525"):s)}else if(l===63||l===35)break}return n.slice(i,c)};var At=(t)=>{let n=Et(t);return n.length>1&&n.at(-1)==="/"?n.slice(0,-1):n},P=(t,n,...i)=>{if(i.length)n=P(n,...i);return`${t?.[0]==="/"?"":"/"}${t}${n==="/"?"":`${t?.at(-1)==="/"?"":"/"}${n?.[0]==="/"?n.slice(1):n}`}`},p=(t)=>{if(t.charCodeAt(t.length-1)!==63||!t.includes(":"))return null;let n=t.split("/"),i=[],c="";return n.forEach((l)=>{if(l!==""&&!/\:/.test(l))c+="/"+l;else if(/\:/.test(l))if(/\?/.test(l)){if(i.length===0&&c==="")i.push("/");else i.push(c);let f=l.replace("?","");c+="/"+f,i.push(c)}else c+="/"+l}),i.filter((l,f,b)=>b.indexOf(l)===f)},et=(t)=>{if(!/[%+]/.test(t))return t;if(t.indexOf("+")!==-1)t=t.replace(/\+/g," ");return t.indexOf("%")!==-1?H(t,rt):t},Zt=(t,n,i)=>{let c;if(!i&&n&&!/[%+]/.test(n)){let b=t.indexOf("?",8);if(b===-1)return;if(!t.startsWith(n,b+1))b=t.indexOf(`&${n}`,b+1);while(b!==-1){let o=t.charCodeAt(b+n.length+1);if(o===61){let s=b+n.length+2,x=t.indexOf("&",s);return et(t.slice(s,x===-1?void 0:x))}else if(o==38||isNaN(o))return"";b=t.indexOf(`&${n}`,b+1)}if(c=/[%+]/.test(t),!c)return}let l={};c??=/[%+]/.test(t);let f=t.indexOf("?",8);while(f!==-1){let b=t.indexOf("&",f+1),o=t.indexOf("=",f);if(o>b&&b!==-1)o=-1;let s=t.slice(f+1,o===-1?b===-1?void 0:b:o);if(c)s=et(s);if(f=b,s==="")continue;let x;if(o===-1)x="";else if(x=t.slice(o+1,b===-1?void 0:b),c)x=et(x);if(i){if(!(l[s]&&Array.isArray(l[s])))l[s]=[];l[s].push(x)}else l[s]??=x}return n?l[n]:l},Mt=Zt,Ut=(t,n)=>{return Zt(t,n,!0)},rt=decodeURIComponent;var mt=(t)=>H(t,rt),I=class{raw;#t;#n;routeIndex=0;path;bodyCache={};constructor(t,n="/",i=[[]]){this.raw=t,this.path=n,this.#n=i,this.#t={}}param(t){return t?this.#i(t):this.#f()}#i(t){let n=this.#n[0][this.routeIndex][1][t],i=this.#l(n);return i&&/\%/.test(i)?mt(i):i}#f(){let t={},n=Object.keys(this.#n[0][this.routeIndex][1]);for(let i of n){let c=this.#l(this.#n[0][this.routeIndex][1][i]);if(c!==void 0)t[i]=/\%/.test(c)?mt(c):c}return t}#l(t){return this.#n[1]?this.#n[1][t]:t}query(t){return Mt(this.url,t)}queries(t){return Ut(this.url,t)}header(t){if(t)return this.raw.headers.get(t)??void 0;let n={};return this.raw.headers.forEach((i,c)=>{n[c]=i}),n}async parseBody(t){return Wt(this,t)}#c=(t)=>{let{bodyCache:n,raw:i}=this,c=n[t];if(c)return c;let l=Object.keys(n)[0];if(l)return n[l].then((f)=>{if(l==="json")f=JSON.stringify(f);return new Response(f)[t]()});return n[t]=i[t]()};json(){return this.#c("text").then((t)=>JSON.parse(t))}text(){return this.#c("text")}arrayBuffer(){return this.#c("arrayBuffer")}bytes(){return this.#c("arrayBuffer").then((t)=>new Uint8Array(t))}blob(){return this.#c("blob")}formData(){return this.#c("formData")}addValidatedData(t,n){this.#t[t]=n}valid(t){return this.#t[t]}get url(){return this.raw.url}get method(){return this.raw.method}get[Yt](){return this.#n}get matchedRoutes(){return this.#n[0].map(([[,t]])=>t)}get routePath(){return this.#n[0].map(([[,t]])=>t)[this.routeIndex].path}};var Rt={Stringify:1,BeforeStream:2,Stream:3},wn=(t,n)=>{let i=new String(t);return i.isEscaped=!0,i.callbacks=n,i};var dt=async(t,n,i,c,l)=>{if(typeof t==="object"&&!(t instanceof String)){if(!(t instanceof Promise))t=t.toString();if(t instanceof Promise)t=await t}let f=t.callbacks;if(!f?.length)return Promise.resolve(t);if(l)l[0]+=t;else l=[t];let b=Promise.all(f.map((o)=>o({phase:n,buffer:l,context:c}))).then((o)=>Promise.all(o.filter(Boolean).map((s)=>dt(s,n,!1,c,l))).then(()=>l[0]));if(i)return wn(await b,f);else return b};var kn="text/plain; charset=UTF-8",Ot=(t,n)=>{return{"Content-Type":t,...n}},A=(t,n)=>new Response(t,n),yt=class{#t;#n;env={};#i;finalized=!1;error;#f;#l;#c;#e;#o;#x;#s;#u;#E;constructor(t,n){if(this.#t=t,n)this.#l=n.executionCtx,this.env=n.env,this.#x=n.notFoundHandler,this.#E=n.path,this.#u=n.matchResult}get req(){return this.#n??=new I(this.#t,this.#E,this.#u),this.#n}get event(){if(this.#l&&"respondWith"in this.#l)return this.#l;else throw Error("This context has no FetchEvent")}get executionCtx(){if(this.#l)return this.#l;else throw Error("This context has no ExecutionContext")}get res(){return this.#c||=A(null,{headers:this.#s??=new Headers})}set res(t){if(this.#c&&t){t=A(t.body,t);for(let[n,i]of this.#c.headers.entries()){if(n==="content-type")continue;if(n==="set-cookie"){let c=this.#c.headers.getSetCookie();t.headers.delete("set-cookie");for(let l of c)t.headers.append("set-cookie",l)}else t.headers.set(n,i)}}this.#c=t,this.finalized=!0}render=(...t)=>{return this.#o??=(n)=>this.html(n),this.#o(...t)};setLayout=(t)=>this.#e=t;getLayout=()=>this.#e;setRenderer=(t)=>{this.#o=t};header=(t,n,i)=>{if(this.finalized)this.#c=A(this.#c.body,this.#c);let c=this.#c?this.#c.headers:this.#s??=new Headers;if(n===void 0)c.delete(t);else if(i?.append)c.append(t,n);else c.set(t,n)};status=(t)=>{this.#f=t};set=(t,n)=>{this.#i??=new Map,this.#i.set(t,n)};get=(t)=>{return this.#i?this.#i.get(t):void 0};get var(){if(!this.#i)return{};return Object.fromEntries(this.#i)}#b(t,n,i){let c=this.#c?new Headers(this.#c.headers):this.#s??new Headers;if(typeof n==="object"&&"headers"in n){let f=n.headers instanceof Headers?n.headers:new Headers(n.headers);for(let[b,o]of f)if(b.toLowerCase()==="set-cookie")c.append(b,o);else c.set(b,o)}if(i)for(let[f,b]of Object.entries(i))if(typeof b==="string")c.set(f,b);else{c.delete(f);for(let o of b)c.append(f,o)}let l=typeof n==="number"?n:n?.status??this.#f;return A(t,{status:l,headers:c})}newResponse=(...t)=>this.#b(...t);body=(t,n,i)=>this.#b(t,n,i);text=(t,n,i)=>{return!this.#s&&!this.#f&&!n&&!i&&!this.finalized?new Response(t):this.#b(t,n,Ot(kn,i))};json=(t,n,i)=>{return this.#b(JSON.stringify(t),n,Ot("application/json",i))};html=(t,n,i)=>{let c=(l)=>this.#b(l,n,Ot("text/html; charset=UTF-8",i));return typeof t==="object"?dt(t,Rt.Stringify,!1,{}).then(c):c(t)};redirect=(t,n)=>{let i=String(t);return this.header("Location",!/[^\x00-\xFF]/.test(i)?i:encodeURI(i)),this.newResponse(null,n??302)};notFound=()=>{return this.#x??=()=>A(),this.#x(this)}};var O="ALL",wt="all",kt=["get","post","put","delete","options","patch"],h="Can not add a route since the matcher is already built.",q=class extends Error{};var Ft="__COMPOSED_HANDLER";var Fn=(t)=>{return t.text("404 Not Found",404)},Dt=(t,n)=>{if("getResponse"in t){let i=t.getResponse();return n.newResponse(i.body,i)}return console.error(t),n.text("Internal Server Error",500)},It=class t{get;post;put;delete;options;patch;all;on;use;router;getPath;_basePath="/";#t="/";routes=[];constructor(n={}){[...kt,wt].forEach((f)=>{this[f]=(b,...o)=>{if(typeof b==="string")this.#t=b;else this.#f(f,this.#t,b);return o.forEach((s)=>{this.#f(f,this.#t,s)}),this}}),this.on=(f,b,...o)=>{for(let s of[b].flat()){this.#t=s;for(let x of[f].flat())o.map((e)=>{this.#f(x.toUpperCase(),this.#t,e)})}return this},this.use=(f,...b)=>{if(typeof f==="string")this.#t=f;else this.#t="*",b.unshift(f);return b.forEach((o)=>{this.#f(O,this.#t,o)}),this};let{strict:c,...l}=n;Object.assign(this,l),this.getPath=c??!0?n.getPath??Et:At}#n(){let n=new t({router:this.router,getPath:this.getPath});return n.errorHandler=this.errorHandler,n.#i=this.#i,n.routes=this.routes,n}#i=Fn;errorHandler=Dt;route(n,i){let c=this.basePath(n);return i.routes.map((l)=>{let f;if(i.errorHandler===Dt)f=l.handler;else f=async(b,o)=>(await xt([],i.errorHandler)(b,()=>l.handler(b,o))).res,f[Ft]=l.handler;c.#f(l.method,l.path,f,l.basePath)}),this}basePath(n){let i=this.#n();return i._basePath=P(this._basePath,n),i}onError=(n)=>{return this.errorHandler=n,this};notFound=(n)=>{return this.#i=n,this};mount(n,i,c){let l,f;if(c)if(typeof c==="function")f=c;else if(f=c.optionHandler,c.replaceRequest===!1)l=(s)=>s;else l=c.replaceRequest;let b=f?(s)=>{let x=f(s);return Array.isArray(x)?x:[x]}:(s)=>{let x=void 0;try{x=s.executionCtx}catch{}return[s.env,x]};l||=(()=>{let s=P(this._basePath,n),x=s==="/"?0:s.length;return(e)=>{let u=new URL(e.url);return u.pathname=this.getPath(e).slice(x)||"/",new Request(u,e)}})();let o=async(s,x)=>{let e=await i(l(s.req.raw),...b(s));if(e)return e;await x()};return this.#f(O,P(n,"*"),o),this}#f(n,i,c,l){n=n.toUpperCase(),i=P(this._basePath,i);let f={basePath:l!==void 0?P(this._basePath,l):this._basePath,path:i,method:n,handler:c};this.router.add(n,i,[c,f]),this.routes.push(f)}#l(n,i){if(n instanceof Error)return this.errorHandler(n,i);throw n}#c(n,i,c,l){if(l==="HEAD")return(async()=>new Response(null,await this.#c(n,i,c,"GET")))();let f=this.getPath(n,{env:c}),b=this.router.match(l,f),o=new yt(n,{path:f,matchResult:b,env:c,executionCtx:i,notFoundHandler:this.#i});if(b[0].length===1){let x;try{x=b[0][0][0][0](o,async()=>{o.res=await this.#i(o)})}catch(e){return this.#l(e,o)}return x instanceof Promise?x.then((e)=>e||(o.finalized?o.res:this.#i(o))).catch((e)=>this.#l(e,o)):x??this.#i(o)}let s=xt(b[0],this.errorHandler,this.#i);return(async()=>{try{let x=await s(o);if(!x.finalized)throw Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return x.res}catch(x){return this.#l(x,o)}})()}fetch=(n,...i)=>{return this.#c(n,i[1],i[0],n.method)};request=(n,i,c,l)=>{if(n instanceof Request)return this.fetch(i?new Request(n,i):n,c,l);return n=n.toString(),this.fetch(new Request(/^https?:\/\//.test(n)?n:`http://localhost${P("/",n)}`,i),c,l)};fire=()=>{addEventListener("fetch",(n)=>{n.respondWith(this.#c(n.request,n,void 0,n.request.method))})}};var Z=[];function tt(t,n){let i=this.buildAllMatchers(),c=(l,f)=>{let b=i[l]||i[O],o=b[2][f];if(o)return o;let s=f.match(b[0]);if(!s)return[[],Z];let x=s.indexOf("",1);return[b[1][x],s]};return this.match=c,c(t,n)}var nt="[^/]+",M=".*",U="(?:|/.*)",T=Symbol(),Dn=new Set(".\\+*[^]$()");function In(t,n){if(t.length===1)return n.length===1?t<n?-1:1:-1;if(n.length===1)return 1;if(t===M||t===U)return 1;else if(n===M||n===U)return-1;if(t===nt)return 1;else if(n===nt)return-1;return t.length===n.length?t<n?-1:1:n.length-t.length}var Ct=class t{#t;#n;#i=Object.create(null);insert(n,i,c,l,f){if(n.length===0){if(this.#t!==void 0)throw T;if(f)return;this.#t=i;return}let[b,...o]=n,s=b==="*"?o.length===0?["","",M]:["","",nt]:b==="/*"?["","",U]:b.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/),x;if(s){let e=s[1],u=s[2]||nt;if(e&&s[2]){if(u===".*")throw T;if(u=u.replace(/^\((?!\?:)(?=[^)]+\)$)/,"(?:"),/\((?!\?:)/.test(u))throw T}if(x=this.#i[u],!x){if(Object.keys(this.#i).some((d)=>d!==M&&d!==U))throw T;if(f)return;if(x=this.#i[u]=new t,e!=="")x.#n=l.varIndex++}if(!f&&e!=="")c.push([e,x.#n])}else if(x=this.#i[b],!x){if(Object.keys(this.#i).some((e)=>e.length>1&&e!==M&&e!==U))throw T;if(f)return;x=this.#i[b]=new t}x.insert(o,i,c,l,f)}buildRegExpStr(){let i=Object.keys(this.#i).sort(In).map((c)=>{let l=this.#i[c];return(typeof l.#n==="number"?`(${c})@${l.#n}`:Dn.has(c)?`\\${c}`:c)+l.buildRegExpStr()});if(typeof this.#t==="number")i.unshift(`#${this.#t}`);if(i.length===0)return"";if(i.length===1)return i[0];return"(?:"+i.join("|")+")"}};var Ht=class{#t={varIndex:0};#n=new Ct;insert(t,n,i){let c=[],l=[];for(let b=0;;){let o=!1;if(t=t.replace(/\{[^}]+\}/g,(s)=>{let x=`@\\${b}`;return l[b]=[x,s],b++,o=!0,x}),!o)break}let f=t.match(/(?::[^\/]+)|(?:\/\*$)|./g)||[];for(let b=l.length-1;b>=0;b--){let[o]=l[b];for(let s=f.length-1;s>=0;s--)if(f[s].indexOf(o)!==-1){f[s]=f[s].replace(o,l[b][1]);break}}return this.#n.insert(f,n,c,this.#t,i),c}buildRegExp(){let t=this.#n.buildRegExpStr();if(t==="")return[/^$/,[],[]];let n=0,i=[],c=[];return t=t.replace(/#(\d+)|@(\d+)|\.\*\$/g,(l,f,b)=>{if(f!==void 0)return i[++n]=Number(f),"$()";if(b!==void 0)return c[Number(b)]=++n,"";return""}),[new RegExp(`^${t}`),i,c]}};var Cn=[/^$/,[],Object.create(null)],pt=Object.create(null);function ht(t){return pt[t]??=new RegExp(t==="*"?"":`^${t.replace(/\/\*$|([.\\+*[^\]$()])/g,(n,i)=>i?`\\${i}`:"(?:|/.*)")}$`)}function Hn(){pt=Object.create(null)}function pn(t){let n=new Ht,i=[];if(t.length===0)return Cn;let c=t.map((x)=>[!/\*|\/:/.test(x[0]),...x]).sort(([x,e],[u,d])=>x?1:u?-1:e.length-d.length),l=Object.create(null);for(let x=0,e=-1,u=c.length;x<u;x++){let[d,r,y]=c[x];if(d)l[r]=[y.map(([S])=>[S,Object.create(null)]),Z];else e++;let $;try{$=n.insert(r,e,d)}catch(S){throw S===T?new q(r):S}if(d)continue;i[e]=y.map(([S,N])=>{let L=Object.create(null);N-=1;for(;N>=0;N--){let[J,bt]=$[N];L[J]=bt}return[S,L]})}let[f,b,o]=n.buildRegExp();for(let x=0,e=i.length;x<e;x++)for(let u=0,d=i[x].length;u<d;u++){let r=i[x][u]?.[1];if(!r)continue;let y=Object.keys(r);for(let $=0,S=y.length;$<S;$++)r[y[$]]=o[r[y[$]]]}let s=[];for(let x in b)s[x]=i[b[x]];return[f,s,l]}function X(t,n){if(!t)return;for(let i of Object.keys(t).sort((c,l)=>l.length-c.length))if(ht(i).test(n))return[...t[i]];return}var it=class{name="RegExpRouter";#t;#n;constructor(){this.#t={[O]:Object.create(null)},this.#n={[O]:Object.create(null)}}add(t,n,i){let c=this.#t,l=this.#n;if(!c||!l)throw Error(h);if(!c[t])[c,l].forEach((o)=>{o[t]=Object.create(null),Object.keys(o[O]).forEach((s)=>{o[t][s]=[...o[O][s]]})});if(n==="/*")n="*";let f=(n.match(/\/:/g)||[]).length;if(/\*$/.test(n)){let o=ht(n);if(t===O)Object.keys(c).forEach((s)=>{c[s][n]||=X(c[s],n)||X(c[O],n)||[]});else c[t][n]||=X(c[t],n)||X(c[O],n)||[];Object.keys(c).forEach((s)=>{if(t===O||t===s)Object.keys(c[s]).forEach((x)=>{o.test(x)&&c[s][x].push([i,f])})}),Object.keys(l).forEach((s)=>{if(t===O||t===s)Object.keys(l[s]).forEach((x)=>o.test(x)&&l[s][x].push([i,f]))});return}let b=p(n)||[n];for(let o=0,s=b.length;o<s;o++){let x=b[o];Object.keys(l).forEach((e)=>{if(t===O||t===e)l[e][x]||=[...X(c[e],x)||X(c[O],x)||[]],l[e][x].push([i,f-s+o+1])})}}match=tt;buildAllMatchers(){let t=Object.create(null);return Object.keys(this.#n).concat(Object.keys(this.#t)).forEach((n)=>{t[n]||=this.#i(n)}),this.#t=this.#n=void 0,Hn(),t}#i(t){let n=[],i=t===O;if([this.#t,this.#n].forEach((c)=>{let l=c[t]?Object.keys(c[t]).map((f)=>[f,c[t][f]]):[];if(l.length!==0)i||=!0,n.push(...l);else if(t!==O)n.push(...Object.keys(c[O]).map((f)=>[f,c[O][f]]))}),!i)return null;else return pn(n)}};var hn=class{name="PreparedRegExpRouter";#t;#n;constructor(t,n){this.#t=t,this.#n=n}#i(t,n){let i=this.#t[t];i[1].forEach((c)=>c&&c.push(n)),Object.values(i[2]).forEach((c)=>c[0].push(n))}#f(t,n,i,c,l){let f=this.#t[t];if(!l)f[2][n][0].push([i,{}]);else c.forEach((b)=>{if(typeof b==="number")f[1][b].push([i,l]);else f[2][b||n][0].push([i,l])})}add(t,n,i){if(!this.#t[t]){let l=this.#t[O],f={};for(let b in l[2])f[b]=[l[2][b][0].slice(),Z];this.#t[t]=[l[0],l[1].map((b)=>Array.isArray(b)?b.slice():0),f]}if(n==="/*"||n==="*"){let l=[i,{}];if(t===O)for(let f in this.#t)this.#i(f,l);else this.#i(t,l);return}let c=this.#n[n];if(!c)throw Error(`Path ${n} is not registered`);for(let[l,f]of c)if(t===O)for(let b in this.#t)this.#f(b,n,i,l,f);else this.#f(t,n,i,l,f)}buildAllMatchers(){return this.#t}match=tt};var Nt=class{name="SmartRouter";#t=[];#n=[];constructor(t){this.#t=t.routers}add(t,n,i){if(!this.#n)throw Error(h);this.#n.push([t,n,i])}match(t,n){if(!this.#n)throw Error("Fatal error");let i=this.#t,c=this.#n,l=i.length,f=0,b;for(;f<l;f++){let o=i[f];try{for(let s=0,x=c.length;s<x;s++)o.add(...c[s]);b=o.match(t,n)}catch(s){if(s instanceof q)continue;throw s}this.match=o.match.bind(o),this.#t=[o],this.#n=void 0;break}if(f===l)throw Error("Fatal error");return this.name=`SmartRouter + ${this.activeRouter.name}`,b}get activeRouter(){if(this.#n||this.#t.length!==1)throw Error("No active router has been determined yet.");return this.#t[0]}};var m=Object.create(null),qn=(t)=>{for(let n in t)return!0;return!1},qt=class t{#t;#n;#i;#f=0;#l=m;constructor(n,i,c){if(this.#n=c||Object.create(null),this.#t=[],n&&i){let l=Object.create(null);l[n]={handler:i,possibleKeys:[],score:0},this.#t=[l]}this.#i=[]}insert(n,i,c){this.#f=++this.#f;let l=this,f=Vt(i),b=[];for(let o=0,s=f.length;o<s;o++){let x=f[o],e=f[o+1],u=gt(x,e),d=Array.isArray(u)?u[0]:x;if(d in l.#n){if(l=l.#n[d],u)b.push(u[1]);continue}if(l.#n[d]=new t,u)l.#i.push(u),b.push(u[1]);l=l.#n[d]}return l.#t.push({[n]:{handler:c,possibleKeys:b.filter((o,s,x)=>x.indexOf(o)===s),score:this.#f}}),l}#c(n,i,c,l,f){for(let b=0,o=i.#t.length;b<o;b++){let s=i.#t[b],x=s[c]||s[O],e={};if(x!==void 0){if(x.params=Object.create(null),n.push(x),l!==m||f&&f!==m)for(let u=0,d=x.possibleKeys.length;u<d;u++){let r=x.possibleKeys[u],y=e[x.score];x.params[r]=f?.[r]&&!y?f[r]:l[r]??f?.[r],e[x.score]=!0}}}}search(n,i){let c=[];this.#l=m;let f=[this],b=ut(i),o=[],s=b.length,x=null;for(let e=0;e<s;e++){let u=b[e],d=e===s-1,r=[];for(let $=0,S=f.length;$<S;$++){let N=f[$],L=N.#n[u];if(L)if(L.#l=N.#l,d){if(L.#n["*"])this.#c(c,L.#n["*"],n,N.#l);this.#c(c,L,n,N.#l)}else r.push(L);for(let J=0,bt=N.#i.length;J<bt;J++){let Gt=N.#i[J],j=N.#l===m?{}:{...N.#l};if(Gt==="*"){let a=N.#n["*"];if(a)this.#c(c,a,n,N.#l),a.#l=j,r.push(a);continue}let[Jn,Qt,V]=Gt;if(!u&&!(V instanceof RegExp))continue;let K=N.#n[Jn];if(V instanceof RegExp){if(x===null){x=Array(s);let D=i[0]==="/"?1:0;for(let g=0;g<s;g++)x[g]=D,D+=b[g].length+1}let a=i.substring(x[e]),st=V.exec(a);if(st){if(j[Qt]=st[0],this.#c(c,K,n,N.#l,j),qn(K.#n)){K.#l=j;let D=st[0].match(/\//)?.length??0;(o[D]||=[]).push(K)}continue}}if(V===!0||V.test(u))if(j[Qt]=u,d){if(this.#c(c,K,n,j,N.#l),K.#n["*"])this.#c(c,K.#n["*"],n,j,N.#l)}else K.#l=j,r.push(K)}}let y=o.shift();f=y?r.concat(y):r}if(c.length>1)c.sort((e,u)=>{return e.score-u.score});return[c.map(({handler:e,params:u})=>[e,u])]}};var $t=class{name="TrieRouter";#t;constructor(){this.#t=new qt}add(t,n,i){let c=p(n);if(c){for(let l=0,f=c.length;l<f;l++)this.#t.insert(t,c[l],i);return}this.#t.insert(t,n,i)}match(t,n){return this.#t.search(t,n)}};var St=class extends It{constructor(t={}){super(t);this.router=t.router??new Nt({routers:[new it,new $t]})}};import ti from"os";import vt from"path";var E={port:Number(process.env.JUNSO_BROWSER_PORT??8790),host:process.env.JUNSO_BROWSER_HOST??"127.0.0.1",token:process.env.JUNSO_BROWSER_TOKEN??"",dataDir:process.env.JUNSO_BROWSER_DATA_DIR??vt.join(ti.homedir(),".junso-browser"),maxInstances:Number(process.env.JUNSO_BROWSER_MAX_INSTANCES??3),idleReapMs:Number(process.env.JUNSO_BROWSER_IDLE_MS??1800000),cloakPath:process.env.JUNSO_BROWSER_CLOAK_PATH,publicUrl:process.env.JUNSO_BROWSER_PUBLIC_URL};function Bt(){return vt.join(E.dataDir,"profiles.json")}function ct(t){return vt.join(E.dataDir,"profiles",t,"user-data")}function lt(){return E.host==="127.0.0.1"||E.host==="localhost"||E.host==="::1"}import{mkdir as li,readFile as fi,writeFile as bi,rm as si}from"fs/promises";import oi from"path";import{randomUUID as xi}from"crypto";import ni from"os";import zt from"path";import{existsSync as tn,readdirSync as ii}from"fs";function G(){if(E.cloakPath&&tn(E.cloakPath))return E.cloakPath;let t=zt.join(ni.homedir(),".cloakbrowser"),n;try{n=ii(t).filter((c)=>c.startsWith("chromium-"))}catch{return null}n.sort().reverse();let i=process.platform==="win32"?"chrome.exe":"chrome";for(let c of n){let l=zt.join(t,c,i);if(tn(l))return l}return null}var Lt=!1;function nn(){if(Lt)return;if(process.env.JUNSO_BROWSER_NO_CLOAK_DOWNLOAD==="true")return;if(G())return;Lt=!0,console.log("[junso-browser] CloakBrowser binary not found \u2014 downloading in background\u2026");let t=zt.resolve(import.meta.dir,"..");Bun.spawn([process.execPath,"x","cloakbrowser","install"],{cwd:t,stdout:"inherit",stderr:"inherit"}).exited.then((i)=>{Lt=!1,console.log(i===0?"[junso-browser] CloakBrowser ready.":`[junso-browser] cloak download exited ${i}.`)})}function ci(t){try{let n=new URL(t);return`${n.protocol}//${n.host}`}catch{return t}}function cn(t){if(!t)return null;try{let n=new URL(t);if(!n.username)return null;return{username:decodeURIComponent(n.username),password:decodeURIComponent(n.password)}}catch{return null}}function Kt(){return Math.floor(Math.random()*90000)+1e4}function ln(t,n,i){let c=t.fingerprint,l=["--no-sandbox",`--fingerprint=${c.seed}`,`--fingerprint-platform=${c.platform??"windows"}`];if(c.timezone)l.push(`--fingerprint-timezone=${c.timezone}`);if(c.locale)l.push(`--fingerprint-locale=${c.locale}`,`--accept-lang=${c.locale}`);if(t.proxy)l.push(`--proxy-server=${ci(t.proxy)}`);return l.push(`--user-data-dir=${i}`,`--remote-debugging-port=${n}`,"--remote-debugging-address=127.0.0.1","--headless=new"),l}function fn(t){let n={...process.env};if(t.fingerprint.timezone)n.TZ=t.fingerprint.timezone;return n}var Q=null,bn=Promise.resolve();async function R(){if(Q)return Q;try{let t=await fi(Bt(),"utf8"),n=JSON.parse(t);Q=n&&typeof n==="object"?n:{}}catch{Q={}}return Q}async function jt(t){await li(E.dataDir,{recursive:!0}),await bi(Bt(),JSON.stringify(t,null,2)+`
|
|
3
|
+
`,"utf8"),Q=t}function Pt(t){let n=bn.catch(()=>{}).then(t);return bn=n.catch(()=>{}),n}function ei(t){return(t??"").trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}async function sn(){return Object.values(await R()).sort((t,n)=>t.name.localeCompare(n.name))}async function z(t){return(await R())[t]??null}async function on(t){let n=ei(t.name)||xi().slice(0,8);return Pt(async()=>{let i={...await R()};if(i[n])throw Error(`Profile "${n}" already exists`);let c=new Date().toISOString(),l={id:n,name:t.name.trim(),fingerprint:{seed:t.fingerprint?.seed??Kt(),platform:t.fingerprint?.platform??"windows",timezone:t.fingerprint?.timezone,locale:t.fingerprint?.locale},proxy:t.proxy?.trim()||void 0,createdAt:c,updatedAt:c};return i[n]=l,await jt(i),l})}async function Jt(t,n){return Pt(async()=>{let i={...await R()},c=i[t];if(!c)throw Error(`No such profile: ${t}`);let l={...c.fingerprint,...n.fingerprint??{}};if(n.rotateSeed)l.seed=Kt();let f={...c,name:n.name?.trim()||c.name,fingerprint:l,proxy:n.proxy===null?void 0:n.proxy?.trim()||c.proxy,updatedAt:new Date().toISOString()};return i[t]=f,await jt(i),f})}async function xn(t){return Pt(async()=>{let n={...await R()};if(!n[t])return!1;return delete n[t],await jt(n),await si(oi.dirname(ct(t)),{recursive:!0,force:!0}),!0})}function en(t){if(!/session-[a-z0-9]+/i.test(t))return null;let n="s"+Math.random().toString(36).slice(2,10);return t.replace(/session-[a-z0-9]+/i,`session-${n}`)}function ui(t){if(!t)return null;return t.replace(/^([a-z0-9+.-]+:\/\/[^:@/]+):[^@/]+@/i,"$1:\u2022\u2022\u2022\u2022@")}function Y(t){return{...t,proxy:ui(t.proxy)??void 0}}import{mkdir as Ei,readFile as ri,rm as un}from"fs/promises";import _t from"path";class Tt{browserWsUrl;username;password;ws=null;nextId=1;constructor(t,n,i){this.browserWsUrl=t;this.username=n;this.password=i}async start(){let t=new WebSocket(this.browserWsUrl);this.ws=t,await new Promise((n,i)=>{t.onopen=()=>n(),t.onerror=()=>i(Error("proxy-auth CDP connect failed"))}),t.onmessage=(n)=>this.onMessage(JSON.parse(String(n.data))),t.onclose=()=>{this.ws=null},this.send(void 0,"Target.setAutoAttach",{autoAttach:!0,waitForDebuggerOnStart:!1,flatten:!0})}send(t,n,i){this.ws?.send(JSON.stringify({id:this.nextId++,sessionId:t,method:n,params:i}))}onMessage(t){if(t.method==="Target.attachedToTarget"){let n=t.params.sessionId;this.send(n,"Fetch.enable",{handleAuthRequests:!0})}else if(t.method==="Fetch.authRequired"){let n=t.params,i=n.authChallenge?.source==="Proxy";this.send(t.sessionId,"Fetch.continueWithAuth",{requestId:n.requestId,authChallengeResponse:i?{response:"ProvideCredentials",username:this.username,password:this.password}:{response:"Default"}})}else if(t.method==="Fetch.requestPaused")this.send(t.sessionId,"Fetch.continueRequest",{requestId:t.params.requestId})}close(){try{this.ws?.close()}catch{}this.ws=null}}var B=new Map;async function di(t,n=20000){let i=_t.join(t,"DevToolsActivePort"),c=Date.now()+n;while(Date.now()<c){try{let l=await ri(i,"utf8"),[f,b]=l.split(`
|
|
4
|
+
`),o=Number(f);if(o>0&&b)return{port:o,wsPath:b.trim()}}catch{}await Bun.sleep(150)}throw Error("Browser did not become ready (no DevToolsActivePort)")}async function Oi(){let t=null;for(let n of B.values())if(!t||n.instance.lastUsedAt<t.instance.lastUsedAt)t=n;if(t)await _(t.instance.profileId)}async function W(t){let n=B.get(t.id);if(n)return n.instance.lastUsedAt=new Date().toISOString(),n.instance;let i=G();if(!i)throw Error("CloakBrowser binary not found \u2014 run `cloakbrowser install`");if(E.maxInstances>0&&B.size>=E.maxInstances)await Oi();let c=ct(t.id);await Ei(c,{recursive:!0}),await un(_t.join(c,"DevToolsActivePort"),{force:!0}),await un(_t.join(c,"SingletonLock"),{force:!0});let l=ln(t,0,c),f=Bun.spawn([i,...l],{stdout:"ignore",stderr:"ignore",env:fn(t)}),b;try{b=await di(c)}catch(u){throw f.kill(),u}let o=new Date().toISOString(),s={profileId:t.id,pid:f.pid,port:b.port,browserWsPath:b.wsPath,startedAt:o,lastUsedAt:o},x={instance:s,proc:f};B.set(t.id,x);let e=cn(t.proxy);if(e){let u=new Tt(`ws://127.0.0.1:${b.port}${b.wsPath}`,e.username,e.password);try{await u.start(),x.auth=u}catch{}}return f.exited.then(()=>{if(B.get(t.id)?.proc===f)x.auth?.close(),B.delete(t.id)}),s}function ft(t){return B.has(t)}function En(t){let n=B.get(t);if(n)n.instance.lastUsedAt=new Date().toISOString()}async function _(t){let n=B.get(t);if(!n)return!1;return B.delete(t),n.auth?.close(),n.proc.kill(),await n.proc.exited.catch(()=>{}),!0}async function rn(){await Promise.all([...B.keys()].map((t)=>_(t)))}function dn(){return[...B.values()].map((t)=>t.instance)}function On(){if(E.idleReapMs<=0)return null;return setInterval(()=>{let t=Date.now()-E.idleReapMs;for(let n of B.values())if(new Date(n.instance.lastUsedAt).getTime()<t)_(n.instance.profileId)},60000)}async function Ni(t,n=15000){try{return(await(await fetch("https://api.ipify.org?format=json",{proxy:t||void 0,signal:AbortSignal.timeout(n)})).json()).ip??null}catch{return null}}async function $i(t,n=1e4){try{let l=await(await fetch(`http://ip-api.com/json/${t}?fields=status,country,countryCode,timezone,isp,mobile,proxy,hosting,query`,{signal:AbortSignal.timeout(n)})).json();if(l.status!=="success")return null;let f="residential";if(l.proxy)f="proxy";else if(l.hosting)f="hosting";else if(l.mobile)f="mobile";return{ip:l.query??t,country:l.country,countryCode:l.countryCode,timezone:l.timezone,isp:l.isp,kind:f}}catch{return null}}async function w(t){let n=await Ni(t);if(!n)return null;return await $i(n)??{ip:n,kind:"unknown"}}function at(t){return{timezone:t.timezone,locale:t.countryCode?`en-${t.countryCode}`:void 0}}async function yn(t,n,i=38000){let c=`ws://127.0.0.1:${t}${n}`;return new Promise((l)=>{let f=!1,b=null,o=setTimeout(()=>s(null),i);function s(r){if(f)return;f=!0,clearTimeout(o);try{u.close()}catch{}l(r)}let x=0,e=new Map,u=new WebSocket(c);u.onclose=()=>s(null),u.onerror=()=>s(null),u.onmessage=(r)=>{let y=JSON.parse(String(r.data));if(y.id&&e.has(y.id))e.get(y.id)(y.result),e.delete(y.id)};function d(r,y,$){let S=++x;return new Promise((N)=>{e.set(S,N),u.send(JSON.stringify({id:S,method:r,params:y??{},...$?{sessionId:$}:{}}))})}u.onopen=async()=>{try{let{targetId:r}=await d("Target.createTarget",{url:"about:blank"});b=r;let{sessionId:y}=await d("Target.attachToTarget",{targetId:r,flatten:!0});await d("Page.enable",{},y),await d("Runtime.enable",{},y),await d("Page.navigate",{url:"https://antcpt.com/score_detector/"},y);for(let $=0;$<16;$++){await new Promise((J)=>setTimeout(J,2000));let L=((await d("Runtime.evaluate",{expression:'document.body ? document.body.innerText : ""',returnByValue:!0},y))?.result?.value??"").match(/Your score is:?\s*([0-9.]+)/i);if(L){await d("Target.closeTarget",{targetId:r}).catch(()=>{}),s(parseFloat(L[1]??"0"));return}}await d("Target.closeTarget",{targetId:r}).catch(()=>{}),s(null)}catch{if(b)d("Target.closeTarget",{targetId:b}).catch(()=>{});s(null)}}})}var Nn={name:"junso-browser",version:"0.2.7",description:"Standalone CloakBrowser host \u2014 runs fingerprinted stealth-Chromium per profile, exposes each over a token-authed CDP gateway + interactive viewport, and ships an optional MCP server so any client gets browser tools with no local browser.",type:"module",bin:{"junso-browser":"bin/junso-browser.js","junso-browser-mcp":"bin/junso-browser-mcp.js"},files:["bin","dist","README.md"],engines:{bun:">=1.2.0"},keywords:["browser","cloakbrowser","stealth","fingerprint","cdp","mcp","proxy","automation"],license:"UNLICENSED",scripts:{dev:"bun --watch src/server.ts",start:"bun src/server.ts",mcp:"bun src/mcp.ts",build:"bun build src/server.ts src/mcp.ts --target=bun --minify --outdir=dist","build:binary":"bun build src/server.ts --compile --outfile dist/junso-browser",typecheck:"bunx tsc --noEmit",test:"bun test",prepublishOnly:"bun run build"},dependencies:{"agent-browser":"^0.27.1",cloakbrowser:"^0.3.31"},devDependencies:{"@modelcontextprotocol/sdk":"^1.29.0","@types/bun":"latest",hono:"^4.6.0",typescript:"^5.6.0",zod:"3"}};function vi(t){return/^https?:|^file:/.test(t)}class $n{browserWsUrl;cdp=null;sessionId=null;activeTargetId=null;nextId=1;pending=new Map;starting=null;targets=new Map;lastFrame=null;lastUrl=null;viewers=new Set;constructor(t){this.browserWsUrl=t}rpc(t,n={},i){if(!this.cdp)return Promise.reject(Error("cdp closed"));let c=this.nextId++;return this.cdp.send(JSON.stringify({id:c,method:t,params:n,sessionId:i})),new Promise((l)=>this.pending.set(c,l))}async start(){if(this.starting)return this.starting;return this.starting=(async()=>{let t=new WebSocket(this.browserWsUrl);this.cdp=t,await new Promise((l,f)=>{t.onopen=()=>l(),t.onerror=()=>f(Error("CDP connect failed"))}),t.onmessage=(l)=>this.onMessage(JSON.parse(String(l.data))),t.onclose=()=>{this.cdp=null,this.sessionId=null},await this.rpc("Target.setDiscoverTargets",{discover:!0});let{targetInfos:n}=await this.rpc("Target.getTargets"),i=n.filter((l)=>l.type==="page");for(let l of i)this.targets.set(l.targetId,{url:l.url,title:l.title});let c=i.find((l)=>vi(l.url))??i[0];if(!c)throw Error("no page target to stream");await this.attachTo(c.targetId)})(),this.starting}async attachTo(t){if(this.sessionId){let i=this.sessionId;this.sessionId=null;try{await this.rpc("Target.detachFromTarget",{sessionId:i})}catch{}}let{sessionId:n}=await this.rpc("Target.attachToTarget",{targetId:t,flatten:!0});this.sessionId=n,this.activeTargetId=t,await this.rpc("Page.enable",{},n),await this.rpc("Page.startScreencast",{format:"jpeg",quality:60,maxWidth:1280,maxHeight:800,everyNthFrame:1},n);try{let i=await this.rpc("Page.getNavigationHistory",{},n);this.lastUrl=i.entries[i.currentIndex]?.url??null}catch{}if(this.broadcastTabs(),this.lastUrl)this.broadcast({type:"url",url:this.lastUrl})}async switchTarget(t){if(!this.targets.has(t)||t===this.activeTargetId)return;this.lastFrame=null,await this.attachTo(t).catch(()=>{})}tabList(){return[...this.targets.entries()].map(([t,n])=>({targetId:t,url:n.url,title:n.title,active:t===this.activeTargetId}))}broadcastTabs(){this.broadcast({type:"tabs",tabs:this.tabList()})}onMessage(t){if(t.id!==void 0&&this.pending.has(t.id)){this.pending.get(t.id)(t.result),this.pending.delete(t.id);return}if(t.method==="Page.screencastFrame"){let n=t.params;this.rpc("Page.screencastFrameAck",{sessionId:n.sessionId},this.sessionId??void 0);let i=JSON.stringify({type:"frame",data:n.data,metadata:n.metadata});this.lastFrame=i;for(let c of this.viewers)c.send(i)}else if(t.method==="Page.frameNavigated"){let n=t.params.frame;if(n&&!n.parentId&&n.url){if(this.lastUrl=n.url,this.activeTargetId){let i=this.targets.get(this.activeTargetId);if(i)i.url=n.url}this.broadcast({type:"url",url:n.url})}}else if(t.method==="Target.targetCreated"||t.method==="Target.targetInfoChanged"){let n=t.params.targetInfo;if(n&&n.type==="page")this.targets.set(n.targetId,{url:n.url,title:n.title}),this.broadcastTabs()}else if(t.method==="Target.targetDestroyed"){let n=t.params.targetId;if(this.targets.delete(n)){if(this.broadcastTabs(),n===this.activeTargetId){let i=[...this.targets.keys()][0];if(i)this.switchTarget(i)}}}}broadcast(t){let n=JSON.stringify(t);for(let i of this.viewers)i.send(n)}sendStateTo(t){if(this.lastFrame)t.send(this.lastFrame);if(this.lastUrl)t.send(JSON.stringify({type:"url",url:this.lastUrl}));t.send(JSON.stringify({type:"tabs",tabs:this.tabList()}))}input(t){if(!this.cdp||!this.sessionId)return;let n=t.t;if(n==="m")this.rpc("Input.dispatchMouseEvent",{type:t.type,x:t.x,y:t.y,button:t.button??"none",buttons:t.buttons??0,clickCount:t.clickCount??0,deltaX:t.deltaX??0,deltaY:t.deltaY??0,modifiers:t.modifiers??0},this.sessionId);else if(n==="k")this.rpc("Input.dispatchKeyEvent",{type:t.type,key:t.key,code:t.code,text:t.text,windowsVirtualKeyCode:t.keyCode,nativeVirtualKeyCode:t.keyCode,modifiers:t.modifiers??0},this.sessionId);else if(n==="tab"){let i=String(t.targetId??"");if(i)this.switchTarget(i)}else if(n==="nav"){let i=String(t.url??"").trim();if(i)this.rpc("Page.navigate",{url:/^[a-z]+:\/\//i.test(i)?i:`https://${i}`},this.sessionId)}else if(n==="reload")this.rpc("Page.reload",{},this.sessionId);else if(n==="back"||n==="forward")(async()=>{let i=await this.rpc("Page.getNavigationHistory",{},this.sessionId),c=i.currentIndex+(n==="forward"?1:-1),l=i.entries[c];if(l)await this.rpc("Page.navigateToHistoryEntry",{entryId:l.id},this.sessionId)})()}close(){try{this.cdp?.close()}catch{}this.cdp=null}}var k=new Map;async function Sn(t,n){let i=await z(t);if(!i)throw Error(`no such profile: ${t}`);let c=await W(i),l=k.get(t);if(!l)l=new $n(`ws://127.0.0.1:${c.port}${c.browserWsPath}`),k.set(t,l);await l.start(),l.viewers.add(n),l.sendStateTo(n)}function vn(t,n){let i=k.get(t);if(!i)return;if(i.viewers.delete(n),i.viewers.size===0)i.close(),k.delete(t)}function Bn(t,n){let i=k.get(t);if(!i)return;try{i.input(JSON.parse(n))}catch{}}function Ln(t,n){let i=JSON.stringify(t),c=JSON.stringify(n||"");return`<!doctype html>
|
|
5
5
|
<html><head><meta charset="utf-8"><title>junso-browser \xB7 ${t}</title>
|
|
6
6
|
<style>
|
|
7
7
|
html,body{margin:0;height:100%;background:#111;color:#ccc;font:13px system-ui}
|
|
@@ -78,7 +78,7 @@ img.addEventListener("contextmenu",e=>e.preventDefault());
|
|
|
78
78
|
img.addEventListener("wheel",e=>{e.preventDefault();const p=pos(e);send({t:"m",type:"mouseWheel",x:p.x,y:p.y,deltaX:e.deltaX,deltaY:e.deltaY,modifiers:mods(e)});},{passive:false});
|
|
79
79
|
img.addEventListener("keydown",e=>{e.preventDefault();const printable=e.key.length===1; send({t:"k",type:"keyDown",key:e.key,code:e.code,keyCode:e.keyCode,modifiers:mods(e),text:printable?e.key:undefined});});
|
|
80
80
|
img.addEventListener("keyup",e=>{e.preventDefault();send({t:"k",type:"keyUp",key:e.key,code:e.code,keyCode:e.keyCode,modifiers:mods(e)});});
|
|
81
|
-
</script></body></html>`}function
|
|
81
|
+
</script></body></html>`}function zn(t){return`<!doctype html><html><head><meta charset="utf-8"><title>junso-browser</title>
|
|
82
82
|
<style>
|
|
83
83
|
:root{color-scheme:dark}
|
|
84
84
|
body{margin:0;background:#0f0f10;color:#ddd;font:14px system-ui;padding:20px;max-width:1100px;margin:0 auto}
|
|
@@ -184,5 +184,5 @@ document.getElementById("rows").addEventListener("click",async function(e){
|
|
|
184
184
|
}catch(e){ err(e.message); }
|
|
185
185
|
});
|
|
186
186
|
load(); setInterval(load,5000);
|
|
187
|
-
</script></body></html>`}var
|
|
188
|
-
Set JUNSO_BROWSER_TOKEN (the CDP endpoint = full browser control).`),process.exit(1);var
|
|
187
|
+
</script></body></html>`}var Kn=Nn.version;function Bi(t,n){let i=t.headers.get("authorization");if(i?.startsWith("Bearer "))return i.slice(7);return t.headers.get("x-junso-token")??n.searchParams.get("token")}function F(t,n){if(!E.token)return lt();return Bi(t,n)===E.token}function Xt(t){let n=E.publicUrl?.replace(/\/$/,"")??`ws://${E.host==="0.0.0.0"?"127.0.0.1":E.host}:${E.port}`,i=E.token?`?token=${encodeURIComponent(E.token)}`:"";return`${n}/cdp/${t}${i}`}async function Li(t,n,i){if(!F(t,n))return new Response("Unauthorized",{status:401});let c=n.pathname.slice(5),l=c.split("/")[0]??"",f=await z(l);if(!f)return new Response("No such profile",{status:404});let b;try{b=await W(f)}catch(s){return new Response(`Launch failed: ${s instanceof Error?s.message:s}`,{status:502})}if(En(l),t.headers.get("upgrade")?.toLowerCase()==="websocket"){let s=`ws://127.0.0.1:${b.port}${b.browserWsPath}`;return i.upgrade(t,{data:{kind:"cdp",profileId:l,targetWsUrl:s,upstream:null,queue:[],closed:!1}})?void 0:new Response("WebSocket upgrade required",{status:426})}let o=c.slice(l.length);if(o.startsWith("/json"))try{let s=await fetch(`http://127.0.0.1:${b.port}${o}`),x=await s.text(),e=Xt(l);return x=x.replace(/ws:\/\/127\.0\.0\.1:\d+\/devtools\/browser\/[a-zA-Z0-9-]+/g,e),new Response(x,{status:s.status,headers:{"content-type":"application/json"}})}catch{return new Response("CDP discovery failed",{status:502})}return new Response("Not found",{status:404})}var zi={open(t){if(t.data.kind==="stream"){let c={send:(l)=>t.send(l)};t.data.viewer=c,Sn(t.data.profileId,c).catch(()=>t.close());return}let n=t.data,i=new WebSocket(n.targetWsUrl);i.binaryType="arraybuffer",n.upstream=i,i.onopen=()=>{for(let c of n.queue)i.send(c);n.queue=[]},i.onmessage=(c)=>{if(!n.closed)t.send(c.data)},i.onclose=()=>{if(!n.closed)t.close()},i.onerror=()=>{if(!n.closed)t.close()}},message(t,n){if(t.data.kind==="stream"){if(typeof n==="string")Bn(t.data.profileId,n);return}let i=t.data.upstream,c=typeof n==="string"?n:new Uint8Array(n).buffer;if(i&&i.readyState===WebSocket.OPEN)i.send(c);else t.data.queue.push(c)},close(t){if(t.data.kind==="stream"){if(t.data.viewer)vn(t.data.profileId,t.data.viewer);return}t.data.closed=!0;try{t.data.upstream?.close()}catch{}}},v=new St;v.use("/api/*",async(t,n)=>{if(!F(t.req.raw,new URL(t.req.url)))return t.json({error:"Unauthorized"},401);await n()});v.get("/health",(t)=>t.json({ok:!0,name:"junso-browser",version:Kn,cloak:Boolean(G()),running:dn().length,maxInstances:E.maxInstances}));v.get("/api/profiles",async(t)=>{let n=await sn();return t.json({profiles:n.map((i)=>({...Y(i),running:ft(i.id)}))})});async function jn(t){if(!t.proxy||typeof t.proxy!=="string")return;let n=t.fingerprint??{};if(n.timezone&&n.locale)return;let i=await w(t.proxy);if(!i)return;let c=at(i);if(t.fingerprint={...n},!n.timezone&&c.timezone)t.fingerprint.timezone=c.timezone;if(!n.locale&&c.locale)t.fingerprint.locale=c.locale}v.post("/api/profiles",async(t)=>{let n=await t.req.json().catch(()=>({}));if(!n?.name||typeof n.name!=="string")return t.json({error:"name is required"},400);try{await jn(n);let i=await on(n);return t.json({profile:Y(i)},201)}catch(i){return t.json({error:i instanceof Error?i.message:"create failed"},400)}});v.get("/api/profiles/:id",async(t)=>{let n=await z(t.req.param("id"));if(!n)return t.json({error:"not found"},404);return t.json({profile:Y(n),running:ft(n.id)})});v.patch("/api/profiles/:id",async(t)=>{let n=await t.req.json().catch(()=>({}));try{if(typeof n.proxy==="string")await jn(n);let i=await Jt(t.req.param("id"),n);return t.json({profile:Y(i)})}catch(i){return t.json({error:i instanceof Error?i.message:"update failed"},400)}});v.delete("/api/profiles/:id",async(t)=>{let n=t.req.param("id");return await _(n),await xn(n)?t.json({ok:!0}):t.json({error:"not found"},404)});v.post("/api/profiles/:id/launch",async(t)=>{let n=await z(t.req.param("id"));if(!n)return t.json({error:"not found"},404);try{return await W(n),t.json({cdpUrl:Xt(n.id),running:!0})}catch(i){return t.json({error:i instanceof Error?i.message:"launch failed"},502)}});v.post("/api/profiles/:id/stop",async(t)=>{let n=await _(t.req.param("id"));return t.json({stopped:n})});v.get("/api/profiles/:id/cdp",async(t)=>{let n=await z(t.req.param("id"));if(!n)return t.json({error:"not found"},404);return t.json({cdpUrl:Xt(n.id),running:ft(n.id)})});v.get("/api/profiles/:id/exit-ip",async(t)=>{let n=await z(t.req.param("id"));if(!n)return t.json({error:"not found"},404);let i=await w(n.proxy);if(!i)return t.json({error:"lookup failed",viaProxy:Boolean(n.proxy)},502);let c=Boolean(n.fingerprint.timezone&&i.timezone&&n.fingerprint.timezone!==i.timezone);return t.json({ip:i.ip,viaProxy:Boolean(n.proxy),country:i.country??null,countryCode:i.countryCode??null,isp:i.isp??null,kind:i.kind,timezone:i.timezone??null,tzMismatch:c})});v.get("/api/profiles/:id/probe",async(t)=>{let n=await z(t.req.param("id"));if(!n)return t.json({error:"not found"},404);let i;try{i=await W(n)}catch(f){return t.json({error:`launch failed: ${f instanceof Error?f.message:f}`},502)}let[c,l]=await Promise.all([yn(i.port,i.browserWsPath),w(n.proxy)]);return t.json({score:c,clean:c!==null&&c>=0.8,ip:l?.ip??null,isp:l?.isp??null,kind:l?.kind??null})});v.post("/api/profiles/:id/rotate-proxy",async(t)=>{let n=await z(t.req.param("id"));if(!n)return t.json({error:"not found"},404);if(!n.proxy)return t.json({error:"profile has no proxy"},400);let i=en(n.proxy);if(!i)return t.json({error:"proxy has no rotatable session-<id> token"},400);let c=await w(i),l=c?at(c):{},f=await Jt(n.id,{proxy:i,fingerprint:l});return await _(n.id),t.json({profile:Y(f),exitIp:c?.ip??null,country:c?.country??null,isp:c?.isp??null,kind:c?.kind??"unknown"})});if(!E.token&&!lt())console.error(`[junso-browser] REFUSING TO START: bound to a non-loopback host with no JUNSO_BROWSER_TOKEN set.
|
|
188
|
+
Set JUNSO_BROWSER_TOKEN (the CDP endpoint = full browser control).`),process.exit(1);var Ki=Bun.serve({port:E.port,hostname:E.host,idleTimeout:0,async fetch(t,n){let i=new URL(t.url);if(i.pathname.startsWith("/cdp/"))return Li(t,i,n);if(i.pathname==="/"||i.pathname==="/dashboard"){if(!F(t,i))return new Response("Unauthorized",{status:401});return new Response(zn(E.token),{headers:{"content-type":"text/html; charset=utf-8"}})}if(i.pathname.startsWith("/view/")){if(!F(t,i))return new Response("Unauthorized",{status:401});let c=i.pathname.slice(6).split("/")[0]??"";return new Response(Ln(c,E.token),{headers:{"content-type":"text/html; charset=utf-8"}})}if(i.pathname.startsWith("/stream/")){if(!F(t,i))return new Response("Unauthorized",{status:401});let c=i.pathname.slice(8).split("/")[0]??"";return n.upgrade(t,{data:{kind:"stream",profileId:c,viewer:null}})?void 0:new Response("WebSocket upgrade required",{status:426})}return v.fetch(t)},websocket:zi});nn();On();var Pn=async()=>{await rn(),process.exit(0)};process.on("SIGINT",Pn);process.on("SIGTERM",Pn);console.log(`[junso-browser] v${Kn} on http://${E.host}:${Ki.port} (cloak ${G()?"found":"MISSING"}, auth ${E.token?"token":lt()?"loopback-open":"off"})`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "junso-browser",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Standalone CloakBrowser host — runs fingerprinted stealth-Chromium per profile, exposes each over a token-authed CDP gateway + interactive viewport, and ships an optional MCP server so any client gets browser tools with no local browser.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|