oh-my-pr 4.5.0 → 4.5.1

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/index.cjs CHANGED
@@ -1108,8 +1108,8 @@ data: ${JSON.stringify(e)}
1108
1108
 
1109
1109
  `)!==!1}function Lne(t,e){let r=e.githubTokens??(e.githubToken!==void 0?[e.githubToken]:void 0);if(r===void 0)return e;let{githubToken:n,...i}=e;return{...i,githubTokens:One(t.githubTokens,r)}}function q8(t){let e=t.githubTokens.map($8);return{...t,githubTokens:e,githubToken:e[0]??""}}async function H8(t,e,r={}){let n=r.runtime??M8(r),i=r.appUpdateChecker??U8();return await n.start(),t.on("close",()=>{n.stop()}),e.get("/api/runtime",async(s,a)=>{a.json(await n.getRuntimeSnapshot())}),e.get("/api/server-logs",(s,a)=>{let o=W0({level:Pne(s.query.level),source:typeof s.query.source=="string"?s.query.source:void 0,since:Id(s.query.since),search:typeof s.query.search=="string"?s.query.search:void 0,limit:Id(s.query.limit)??500});a.json({records:o,sources:fP(),latestSeq:o.length>0?o[o.length-1].seq:Id(s.query.since)??0})}),e.get("/api/server-logs/stream",(s,a)=>{a.statusCode=200,a.setHeader("Content-Type","text/event-stream"),a.setHeader("Cache-Control","no-cache, no-transform"),a.setHeader("Connection","keep-alive"),a.setHeader("Content-Encoding","identity"),a.setHeader("X-Accel-Buffering","no"),a.flushHeaders?.();let o=!1,u=()=>{},c=setInterval(()=>{a.write(`: heartbeat ${Date.now()}
1110
1110
 
1111
- `)===!1&&l()},2e4),l=()=>{o||(o=!0,clearInterval(c),u(),a.writableEnded||a.end())},d=m=>{Ine(a,m)||l()},p=Id(s.query.since);if(p!==void 0){let m=W0({since:p,limit:1e3});for(let f of m)if(d(f),o)return}u=mP(d),s.on("close",l),s.on("aborted",l)}),e.get("/api/activities",async(s,a)=>{a.json(await n.listActivities())}),e.delete("/api/activities/failed",async(s,a)=>{try{a.json(await n.clearFailedActivities())}catch(o){Ee(a,o)}}),e.post("/api/runtime/drain",async(s,a)=>{try{let o=b.object({enabled:b.boolean(),reason:b.string().optional(),waitForIdle:b.boolean().optional(),timeoutMs:b.number().int().positive().max(6e5).optional()}).parse(s.body),u=await n.setDrainMode(o);if(o.enabled&&o.waitForIdle&&u.drained===!1)return a.status(202).json(u);a.json(u)}catch(o){Ee(a,o)}}),e.get("/api/repos",async(s,a)=>{a.json(await n.listRepos())}),e.get("/api/repos/settings",async(s,a)=>{a.json(await n.listRepoSettings())}),e.post("/api/repos",async(s,a)=>{try{let{repo:o}=b.object({repo:b.string().min(1)}).parse(s.body);a.status(201).json(await n.addRepo(o))}catch(o){Ee(a,o)}}),e.patch("/api/repos/settings",async(s,a)=>{try{let o=b.object({repo:b.string().min(1),autoCreateReleases:b.boolean().optional(),ownPrsOnly:b.boolean().optional()}).refine(l=>l.autoCreateReleases!==void 0||l.ownPrsOnly!==void 0,"At least one repository setting must be provided").parse(s.body),{repo:u,...c}=o;a.json(await n.updateRepoSettings(u,c))}catch(o){Ee(a,o)}}),e.post("/api/repos/sync",async(s,a)=>{try{a.json(await n.syncRepos())}catch(o){Ee(a,o)}}),e.post("/api/repos/release",async(s,a)=>{try{let{repo:o}=b.object({repo:b.string().min(1)}).parse(s.body);a.status(201).json(await n.createManualRelease(o))}catch(o){Ee(a,o)}}),e.get("/api/prs",async(s,a)=>{a.json(await n.listPRs("active"))}),e.get("/api/prs/archived",async(s,a)=>{a.json(await n.listPRs("archived"))}),e.get("/api/prs/:id",async(s,a)=>{let o=await n.getPR(s.params.id);if(!o)return a.status(404).json({error:"PR not found"});a.json(o)}),e.post("/api/prs",async(s,a)=>{try{a.status(201).json(await n.addPR(s.body?.url))}catch(o){Ee(a,o)}}),e.delete("/api/prs/:id",async(s,a)=>{try{a.json(await n.removePR(s.params.id))}catch(o){Ee(a,o)}}),e.patch("/api/prs/:id/watch",async(s,a)=>{try{let{enabled:o}=b.object({enabled:b.boolean()}).parse(s.body);a.json(await n.setPRWatchEnabled(s.params.id,o))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/fetch",async(s,a)=>{try{a.json(await n.fetchPRFeedback(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/triage",async(s,a)=>{try{a.json(await n.triagePR(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/apply",async(s,a)=>{try{a.json(await n.applyPR(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/babysit",async(s,a)=>{try{a.json(await n.babysitPR(s.params.id))}catch(o){Ee(a,o)}}),e.patch("/api/prs/:id/feedback/:feedbackId",async(s,a)=>{try{let{decision:o}=b.object({decision:b.enum(["accept","reject","flag"])}).parse(s.body);a.json(await n.setFeedbackDecision(s.params.id,s.params.feedbackId,o))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/feedback/:feedbackId/retry",async(s,a)=>{try{a.json(await n.retryFeedback(s.params.id,s.params.feedbackId))}catch(o){Ee(a,o)}}),e.get("/api/prs/:id/questions",async(s,a)=>{try{a.json(await n.listPRQuestions(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/questions",async(s,a)=>{try{a.status(201).json(await n.askQuestion(s.params.id,s.body?.question))}catch(o){Ee(a,o)}}),e.get("/api/logs",async(s,a)=>{let o=typeof s.query.prId=="string"?s.query.prId:void 0;a.json(await n.listLogs(o))}),e.get("/api/onboarding/status",async(s,a)=>{try{a.json(await n.getOnboardingStatus())}catch(o){Ee(a,o)}}),e.post("/api/onboarding/install-review",async(s,a)=>{try{let{repo:o,tool:u}=b.object({repo:b.string().min(1),tool:b.enum(["claude","codex"])}).parse(s.body);a.json(await n.installReviewWorkflow(o,u))}catch(o){Ee(a,o)}}),e.get("/api/healing-sessions",async(s,a)=>{try{a.json(await n.listHealingSessions())}catch(o){Ee(a,o)}}),e.get("/api/healing-sessions/:id",async(s,a)=>{try{a.json(await n.getHealingSession(s.params.id))}catch(o){Ee(a,o)}}),e.get("/api/deployment-healing-sessions",async(s,a)=>{try{let o=typeof s.query.repo=="string"?s.query.repo:void 0;a.json(await n.listDeploymentHealingSessions(o))}catch(o){Ee(a,o)}}),e.get("/api/deployment-healing-sessions/:id",async(s,a)=>{try{a.json(await n.getDeploymentHealingSession(s.params.id))}catch(o){Ee(a,o)}}),e.get("/api/config",async(s,a)=>{a.json(q8(await n.getConfig()))}),e.get("/api/app-update",async(s,a)=>{try{a.json(await i("4.5.0"))}catch(o){Ee(a,o)}}),e.get("/api/changelogs",async(s,a)=>{try{a.json(await n.listSocialChangelogs())}catch(o){Ee(a,o)}}),e.get("/api/changelogs/:id",async(s,a)=>{try{a.json(await n.getSocialChangelog(s.params.id))}catch(o){Ee(a,o)}}),e.get("/api/releases",async(s,a)=>{try{a.json(await n.listReleaseRuns())}catch(o){Ee(a,o)}}),e.get("/api/releases/:id",async(s,a)=>{try{a.json(await n.getReleaseRun(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/releases/:id/retry",async(s,a)=>{try{a.json(await n.retryReleaseRun(s.params.id))}catch(o){Ee(a,o)}}),e.patch("/api/config",async(s,a)=>{try{let o=Il.partial().parse(s.body),u=await n.getConfig();a.json(q8(await n.updateConfig(Lne(u,o))))}catch(o){Ee(a,o)}}),t}var pO=je(wg(),1);var aO=require("node:net"),Ky=je(rO(),1),oO=require("node:net"),uO=require("node:buffer"),cO=require("node:crypto"),lO=require("node:net");function _ie(t,e=56){if((0,aO.isIPv6)(t)){let r=new Ky.Address6(t);if(r.is4())return r.to4().correctForm();if(e)return`${new Ky.Address6(`${t}/${e}`).startAddress().correctForm()}/${e}`}return t}var Eie=class{constructor(t){this.validations=t,this.previous=new Map,this.current=new Map,this.localKeys=!0}init(t){this.windowMs=t.windowMs,this.validations?.windowMs(this.windowMs),this.interval&&clearInterval(this.interval),this.interval=setInterval(()=>{this.clearExpired()},this.windowMs),this.interval.unref?.()}async get(t){return this.current.get(t)??this.previous.get(t)}async increment(t){let e=this.getClient(t),r=Date.now();return e.resetTime.getTime()<=r&&this.resetClient(e,r),e.totalHits++,e}async decrement(t){let e=this.getClient(t);e.totalHits>0&&e.totalHits--}async resetKey(t){this.current.delete(t),this.previous.delete(t)}async resetAll(){this.current.clear(),this.previous.clear()}shutdown(){clearInterval(this.interval),this.resetAll()}resetClient(t,e=Date.now()){return t.totalHits=0,t.resetTime.setTime(e+this.windowMs),t}getClient(t){if(this.current.has(t))return this.current.get(t);let e;return this.previous.has(t)?(e=this.previous.get(t),this.previous.delete(t)):(e={totalHits:0,resetTime:new Date},this.resetClient(e)),this.current.set(t,e),e}clearExpired(){this.previous=this.current,this.current=new Map}},Sie={warn(...t){console.warn(...t.reverse())},error(...t){console.error(...t.reverse())}},nO=["draft-6","draft-7","draft-8"],$d=(t,e)=>{let r;if(e){let n=Math.ceil((e.getTime()-Date.now())/1e3);r=Math.max(0,n)}else r=Math.ceil(t/1e3);return r},Tie=t=>{let e=(0,cO.createHash)("sha256");e.update(t);let r=e.digest("hex").slice(0,12);return uO.Buffer.from(r).toString("base64")},kie=(t,e)=>{t.headersSent||(t.setHeader("X-RateLimit-Limit",e.limit.toString()),t.setHeader("X-RateLimit-Remaining",e.remaining.toString()),e.resetTime instanceof Date&&(t.setHeader("Date",new Date().toUTCString()),t.setHeader("X-RateLimit-Reset",Math.ceil(e.resetTime.getTime()/1e3).toString())))},Rie=(t,e,r)=>{if(t.headersSent)return;let n=Math.ceil(r/1e3),i=$d(r,e.resetTime);t.setHeader("RateLimit-Policy",`${e.limit};w=${n}`),t.setHeader("RateLimit-Limit",e.limit.toString()),t.setHeader("RateLimit-Remaining",e.remaining.toString()),typeof i=="number"&&t.setHeader("RateLimit-Reset",i.toString())},Aie=(t,e,r)=>{if(t.headersSent)return;let n=Math.ceil(r/1e3),i=$d(r,e.resetTime);t.setHeader("RateLimit-Policy",`${e.limit};w=${n}`),t.setHeader("RateLimit",`limit=${e.limit}, remaining=${e.remaining}, reset=${i}`)},Pie=(t,e,r,n,i)=>{if(t.headersSent)return;let s=Math.ceil(r/1e3),a=$d(r,e.resetTime),o=Tie(i),u=`r=${e.remaining}; t=${a}`,c=`q=${e.limit}; w=${s}; pk=:${o}:`;t.append("RateLimit",`"${n}"; ${u}`),t.append("RateLimit-Policy",`"${n}"; ${c}`)},Cie=(t,e,r)=>{if(t.headersSent)return;let n=$d(r,e.resetTime);t.setHeader("Retry-After",n.toString())},Oie=t=>{let e={};for(let r of Object.keys(t)){let n=r;t[n]!==void 0&&(e[n]=t[n])}return e},nt=class extends Error{constructor(t,e){let r=`https://express-rate-limit.github.io/${t}/`;super(`${e} See ${r} for more information.`),this.name=this.constructor.name,this.code=t,this.help=r}},Gd=class extends nt{},iO=new Set,sO=new WeakMap,Iie={enabled:{default:!0},disable(){for(let t of Object.keys(this.enabled))this.enabled[t]=!1},ip(t){if(t===void 0)throw new nt("ERR_ERL_UNDEFINED_IP_ADDRESS","An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.");if(!(0,lO.isIP)(t))throw new nt("ERR_ERL_INVALID_IP_ADDRESS",`An invalid 'request.ip' (${t}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`)},trustProxy(t){if(t.app.get("trust proxy")===!0)throw new nt("ERR_ERL_PERMISSIVE_TRUST_PROXY","The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.")},xForwardedForHeader(t){if(t.headers["x-forwarded-for"]&&t.app.get("trust proxy")===!1)throw new nt("ERR_ERL_UNEXPECTED_X_FORWARDED_FOR","The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.")},forwardedHeader(t){if(t.headers.forwarded&&t.ip===t.socket?.remoteAddress)throw new nt("ERR_ERL_FORWARDED_HEADER","The 'Forwarded' header (standardized X-Forwarded-For) is set but currently being ignored. Add a custom keyGenerator to use a value from this header.")},positiveHits(t){if(typeof t!="number"||t<1||t!==Math.round(t))throw new nt("ERR_ERL_INVALID_HITS",`The totalHits value returned from the store must be a positive integer, got ${t}`)},unsharedStore(t){if(iO.has(t)){let e=t?.localKeys?"":" (with a unique prefix)";throw new nt("ERR_ERL_STORE_REUSE",`A Store instance must not be shared across multiple rate limiters. Create a new instance of ${t.constructor.name}${e} for each limiter instead.`)}iO.add(t)},singleCount(t,e,r){let n=sO.get(t);n||(n=new Map,sO.set(t,n));let i=e.localKeys?e:e.constructor.name,s=n.get(i);s||(s=[],n.set(i,s));let a=`${e.prefix??""}${r}`;if(s.includes(a))throw new nt("ERR_ERL_DOUBLE_COUNT",`The hit count for ${r} was incremented more than once for a single request.`);s.push(a)},limit(t){if(t===0)throw new Gd("WRN_ERL_MAX_ZERO","Setting limit or max to 0 disables rate limiting in express-rate-limit v6 and older, but will cause all requests to be blocked in v7")},draftPolliHeaders(t){if(t)throw new Gd("WRN_ERL_DEPRECATED_DRAFT_POLLI_HEADERS","The draft_polli_ratelimit_headers configuration option is deprecated and has been removed in express-rate-limit v7, please set standardHeaders: 'draft-6' instead.")},onLimitReached(t){if(t)throw new Gd("WRN_ERL_DEPRECATED_ON_LIMIT_REACHED","The onLimitReached configuration option is deprecated and has been removed in express-rate-limit v7.")},headersDraftVersion(t){if(typeof t!="string"||!nO.includes(t)){let e=nO.join(", ");throw new nt("ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION",`standardHeaders: only the following versions of the IETF draft specification are supported: ${e}.`)}},headersResetTime(t){if(!t)throw new nt("ERR_ERL_HEADERS_NO_RESET","standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.")},knownOptions(t){if(!t)return;let r=Object.keys({windowMs:!0,limit:!0,message:!0,statusCode:!0,legacyHeaders:!0,standardHeaders:!0,identifier:!0,requestPropertyName:!0,skipFailedRequests:!0,skipSuccessfulRequests:!0,keyGenerator:!0,ipv6Subnet:!0,handler:!0,skip:!0,requestWasSuccessful:!0,store:!0,validate:!0,headers:!0,max:!0,passOnStoreError:!0,logger:!0}).concat("draft_polli_ratelimit_headers","delayAfter","delayMs","maxDelayMs");for(let n of Object.keys(t))if(!r.includes(n))throw new nt("ERR_ERL_UNKNOWN_OPTION",`Unexpected configuration option: ${n}`)},validationsConfig(){let t=Object.keys(this).filter(e=>!["enabled","disable"].includes(e));t.push("default");for(let e of Object.keys(this.enabled))if(!t.includes(e))throw new nt("ERR_ERL_UNKNOWN_VALIDATION",`options.validate.${e} is not recognized. Supported validate options are: ${t.join(", ")}.`)},creationStack(t){let{stack:e}=new Error("express-rate-limit validation check (set options.validate.creationStack=false to disable)");if(e?.includes("Layer.handle [as handle_request]")||e?.includes("Layer.handleRequest"))throw t.localKeys?new nt("ERR_ERL_CREATED_IN_REQUEST_HANDLER","express-rate-limit instance should be created at app initialization, not when responding to a request."):new nt("ERR_ERL_CREATED_IN_REQUEST_HANDLER","express-rate-limit instance should *usually* be created at app initialization, not when responding to a request.")},ipv6Subnet(t){if(t!==!1&&(!Number.isInteger(t)||t<32||t>64))throw new nt("ERR_ERL_IPV6_SUBNET",`Unexpected ipv6Subnet value: ${t}. Expected an integer between 32 and 64 (usually 48-64).`)},ipv6SubnetOrKeyGenerator(t){if(t.ipv6Subnet!==void 0&&t.keyGenerator)throw new nt("ERR_ERL_IPV6SUBNET_OR_KEYGENERATOR","Incompatible options: the 'ipv6Subnet' option is ignored when a custom 'keyGenerator' function is also set.")},keyGeneratorIpFallback(t){if(!t)return;let e=t.toString();if((e.includes("req.ip")||e.includes("request.ip"))&&!e.includes("ipKeyGenerator"))throw new nt("ERR_ERL_KEY_GEN_IPV6","Custom keyGenerator appears to use request IP without calling the ipKeyGenerator helper function for IPv6 addresses. This could allow IPv6 users to bypass limits.")},windowMs(t){if(typeof t!="number"||Number.isNaN(t)||t<1||t>2147483647)throw new nt("ERR_ERL_WINDOW_MS",`Invalid windowMs value: ${t}${typeof t!="number"?` (${typeof t})`:""}, must be a number between 1 and 2147483647 when using the default MemoryStore`)}};function Lie(t){if(typeof t!="object"||typeof t.error!="function"||typeof t.warn!="function")throw new TypeError("Provided logger does not implement the Logger interface")}var Die=(t,e)=>{Lie(e);let r;typeof t=="boolean"?r={default:t}:r={default:!0,...t};let n={enabled:r};for(let[i,s]of Object.entries(Iie))typeof s=="function"&&(n[i]=(...a)=>{if(r[i]??r.default)try{s.apply(n,a)}catch(o){o instanceof Gd?e.warn(o):e.error(o)}});return n},Nie=t=>typeof t.incr=="function"&&typeof t.increment!="function",Fie=t=>{if(!Nie(t))return t;let e=t;class r{async increment(i){return new Promise((s,a)=>{e.incr(i,(o,u,c)=>{o&&a(o),s({totalHits:u,resetTime:c})})})}async decrement(i){return e.decrement(i)}async resetKey(i){return e.resetKey(i)}async resetAll(){if(typeof e.resetAll=="function")return e.resetAll()}}return new r},Mie=t=>{let{validations:e,...r}=t;return{...r,validate:e.enabled}},jie=t=>{let e=Oie(t),r=t.logger??Sie,n=Die(e?.validate??!0,r);n.validationsConfig(),n.knownOptions(t),n.draftPolliHeaders(e.draft_polli_ratelimit_headers),n.onLimitReached(e.onLimitReached),e.ipv6Subnet!==void 0&&typeof e.ipv6Subnet!="function"&&n.ipv6Subnet(e.ipv6Subnet),n.keyGeneratorIpFallback(e.keyGenerator),n.ipv6SubnetOrKeyGenerator(e);let i=e.standardHeaders??!1;i===!0&&(i="draft-6");let s={windowMs:60*1e3,limit:t.max??5,message:"Too many requests, please try again later.",statusCode:429,legacyHeaders:t.headers??!0,identifier(a,o){let u="",c=s.requestPropertyName,{limit:l}=a[c],d=s.windowMs/1e3,p=s.windowMs/(1e3*60),m=s.windowMs/(1e3*60*60),f=s.windowMs/(1e3*60*60*24);return d<60?u=`${d}sec`:p<60?u=`${p}min`:m<24?u=`${m}hr${m>1?"s":""}`:u=`${f}day${f>1?"s":""}`,`${l}-in-${u}`},requestPropertyName:"rateLimit",skipFailedRequests:!1,skipSuccessfulRequests:!1,requestWasSuccessful:(a,o)=>o.statusCode<400,skip:(a,o)=>!1,async keyGenerator(a,o){n.ip(a.ip),n.trustProxy(a),n.xForwardedForHeader(a),n.forwardedHeader(a);let u=a.ip,c=56;return(0,oO.isIPv6)(u)&&(c=typeof s.ipv6Subnet=="function"?await s.ipv6Subnet(a,o):s.ipv6Subnet,typeof s.ipv6Subnet=="function"&&n.ipv6Subnet(c)),_ie(u,c)},ipv6Subnet:56,async handler(a,o,u,c){o.status(s.statusCode);let l=typeof s.message=="function"?await s.message(a,o):s.message;o.writableEnded||o.send(l)},passOnStoreError:!1,...e,standardHeaders:i,store:Fie(e.store??new Eie(n)),validations:n,logger:r};if(typeof s.store.increment!="function"||typeof s.store.decrement!="function"||typeof s.store.resetKey!="function"||s.store.resetAll!==void 0&&typeof s.store.resetAll!="function"||s.store.init!==void 0&&typeof s.store.init!="function")throw new TypeError("An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.");return s},Bie=t=>async(e,r,n)=>{try{await Promise.resolve(t(e,r,n)).catch(n)}catch(i){n(i)}},Uie=t=>{let e=jie(t??{}),r=Mie(e);if(e.validations.creationStack(e.store),e.validations.unsharedStore(e.store),typeof e.store.init=="function")try{let s=e.store.init(r);s instanceof Promise&&s.catch(a=>e.logger.error(a,"express-rate-limit: async error during store initialization."))}catch(s){e.logger.error(s,"express-rate-limit: error during store initialization.")}let n=Bie(async(s,a,o)=>{let u=e.skipFailedRequests&&new Promise(S=>a.once("close",S)),c=(e.skipFailedRequests||e.skipSuccessfulRequests)&&new Promise(S=>a.once("finish",S)),l=e.skipFailedRequests&&new Promise(S=>a.once("error",S));if(await e.skip(s,a)){o();return}let p=s,m=await e.keyGenerator(s,a),f=0,g;try{let S=await e.store.increment(m);f=S.totalHits,g=S.resetTime}catch(S){if(e.passOnStoreError){e.logger.error(S,"express-rate-limit: error from store, allowing request without rate-limiting."),o();return}throw S}e.validations.positiveHits(f),e.validations.singleCount(s,e.store,m);let _=await(typeof e.limit=="function"?e.limit(s,a):e.limit);e.validations.limit(_);let k={limit:_,used:f,remaining:Math.max(_-f,0),resetTime:g,key:m};if(Object.defineProperty(k,"current",{configurable:!1,enumerable:!1,value:f}),p[e.requestPropertyName]=k,e.legacyHeaders&&!a.headersSent&&kie(a,k),e.standardHeaders&&!a.headersSent)switch(e.standardHeaders){case"draft-6":{Rie(a,k,e.windowMs);break}case"draft-7":{e.validations.headersResetTime(k.resetTime),Aie(a,k,e.windowMs);break}case"draft-8":{let C=await(typeof e.identifier=="function"?e.identifier(s,a):e.identifier);e.validations.headersResetTime(k.resetTime),Pie(a,k,e.windowMs,C,m);break}default:{e.validations.headersDraftVersion(e.standardHeaders);break}}if(e.skipFailedRequests||e.skipSuccessfulRequests){let S=!1,C=async()=>{S||(await e.store.decrement(m),S=!0)};e.skipFailedRequests&&(c&&c.then(async()=>{await e.requestWasSuccessful(s,a)||await C()}),u&&u.then(async()=>{a.writableEnded||await C()}),l&&l.then(async()=>{await C()})),e.skipSuccessfulRequests&&c&&c.then(async()=>{await e.requestWasSuccessful(s,a)&&await C()})}if(e.validations.disable(),f>_){(e.legacyHeaders||e.standardHeaders)&&Cie(a,k,e.windowMs),e.handler(s,a,o,r);return}o()}),i=()=>{throw new Error("The current store does not support the get/getKey method")};return n.resetKey=e.store.resetKey.bind(e.store),n.getKey=typeof e.store.get=="function"?e.store.get.bind(e.store):i,n},Hd=Uie;var dO=je(require("fs"),1),Xy=je(require("path"),1),fO=require("url"),$ie={},qie=Hd({windowMs:60*1e3,limit:600,standardHeaders:!0,legacyHeaders:!1});function Gie(){return typeof __dirname=="string"?__dirname:Xy.default.dirname((0,fO.fileURLToPath)($ie.url))}function mO(t,e=Gie()){let r=Xy.default.resolve(e,"public");if(!dO.default.existsSync(r))throw new Error(`Could not find the build directory: ${r}, make sure to build the client first`);t.use(pO.default.static(r)),t.use("/{*path}",qie,(n,i)=>{i.sendFile("index.html",{root:r})})}var pc=je(require("node:crypto"),1),bv=je(eI(),1),SI=je(bI(),1);var iae=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function yI(t){if(!t)return!1;let e=t.replace(/^\[|\]$/g,"");return iae.has(e)?!0:e.startsWith("::ffff:")?e.slice(7).startsWith("127."):!!e.startsWith("127.")}var gv="OH_MY_PR_WEB_USERNAME",hv="OH_MY_PR_WEB_PASSWORD",sae="OH_MY_PR_SESSION_SECRET",vI="oh-my-pr.sid",wI=720*60*1e3,aae=(0,SI.default)(bv.default);function xI(t){let e=t?.trim();return e||void 0}function oae(t=process.env){return{username:xI(t[gv]),password:t[hv],sessionSecret:xI(t[sae])}}function uae(t){return!t.username||!t.password?null:{username:t.username,password:t.password}}function cae(t){return t.ip??t.socket?.remoteAddress}function TI(t){return yI(cae(t))}function _I(t,e){let r=pc.default.createHash("sha256").update(t).digest(),n=pc.default.createHash("sha256").update(e).digest();return pc.default.timingSafeEqual(r,n)}function mv(t,e){let r=!TI(t),n=t.session?.authenticatedWebUser??null,i=!r||!!(e&&n===e.username);return{requiresLogin:r,loginConfigured:e!==null,authenticated:i,username:i&&e?e.username:null}}function lae(t){return new Promise((e,r)=>{t.session.regenerate(n=>{if(n){r(n);return}e()})})}function pae(t){return new Promise((e,r)=>{t.session.save(n=>{if(n){r(n);return}e()})})}function dae(t){return new Promise((e,r)=>{t.session.destroy(n=>{if(n){r(n);return}e()})})}function EI(t,e){let r=e instanceof Error?e.message:String(e);return new Error(`Web auth ${t} failed: ${r}`,{cause:e})}function kI(t,e=oae()){let r=uae(e),n=e.sessionSecret??pc.default.randomBytes(32).toString("hex");t.use((0,bv.default)({name:vI,secret:n,store:new aae({checkPeriod:wI}),resave:!1,saveUninitialized:!1,cookie:{httpOnly:!0,sameSite:"lax",secure:!0,maxAge:wI}}));let i=Hd({windowMs:300*1e3,limit:20,standardHeaders:!0,legacyHeaders:!1});return t.get("/api/auth/status",(s,a)=>{a.json(mv(s,r))}),t.post("/api/auth/login",i,async(s,a,o)=>{if(!r){a.status(403).json({error:"Remote login is not configured",message:`Set ${gv} and ${hv} before using remote web access.`});return}let u=typeof s.body?.username=="string"?s.body.username:"",c=typeof s.body?.password=="string"?s.body.password:"";if(!_I(u,r.username)||!_I(c,r.password)){a.status(401).json({error:"Invalid credentials",message:"Username or password is incorrect."});return}let l="session regeneration";try{await lae(s),s.session.authenticatedWebUser=r.username,l="session save",await pae(s)}catch(d){o(EI(l,d));return}a.json(mv(s,r))}),t.post("/api/auth/logout",async(s,a,o)=>{try{s.session.authenticatedWebUser&&(await dae(s),a.clearCookie(vI))}catch(u){o(EI("session destroy",u));return}a.json(mv(s,r))}),{apiAccessMiddleware(s,a,o){if(TI(s)){o();return}if(!r){a.status(403).json({error:"Remote access is not configured",message:`Set ${gv} and ${hv} to allow remote dashboard login.`});return}if(s.session?.authenticatedWebUser===r.username){o();return}a.status(401).json({error:"Login required",message:"Sign in to use oh-my-pr from this network address."})}}}var AI=require("http");var fae=lr("server"),Ln=(0,Xd.default)(),RI=(0,AI.createServer)(Ln);function mae(t){let e=t?.trim();if(!e||e==="false")return!1;if(e==="true")return!0;let r=Number(e);return Number.isInteger(r)&&r>=0?r:e}Ln.use(Xd.default.json({verify:(t,e,r)=>{t.rawBody=r}}));Ln.use(Xd.default.urlencoded({extended:!1}));Ln.set("trust proxy",mae(process.env.OH_MY_PR_TRUST_PROXY));var gae=kI(Ln);Ln.use("/api",gae.apiAccessMiddleware);function PI(t,e="express"){V0.info({source:e},t)}async function hae(t){let{default:e}=await import("open");await e(t)}(async()=>{await H8(RI,Ln),Ln.use((e,r,n,i)=>{let s=e,a=s.status||s.statusCode||500,o=s.message||"Internal Server Error";return fae.error({err:e instanceof Error?e.message:String(e),status:a},"Internal Server Error"),n.headersSent?i(e):n.status(a).json({message:o})}),mO(Ln);let t=parseInt(process.env.PORT||"5001",10);RI.listen({port:t,host:"0.0.0.0"},()=>{let e=`http://localhost:${t}`;console.log(`
1112
- oh-my-pr v4.5.0
1111
+ `)===!1&&l()},2e4),l=()=>{o||(o=!0,clearInterval(c),u(),a.writableEnded||a.end())},d=m=>{Ine(a,m)||l()},p=Id(s.query.since);if(p!==void 0){let m=W0({since:p,limit:1e3});for(let f of m)if(d(f),o)return}u=mP(d),s.on("close",l),s.on("aborted",l)}),e.get("/api/activities",async(s,a)=>{a.json(await n.listActivities())}),e.delete("/api/activities/failed",async(s,a)=>{try{a.json(await n.clearFailedActivities())}catch(o){Ee(a,o)}}),e.post("/api/runtime/drain",async(s,a)=>{try{let o=b.object({enabled:b.boolean(),reason:b.string().optional(),waitForIdle:b.boolean().optional(),timeoutMs:b.number().int().positive().max(6e5).optional()}).parse(s.body),u=await n.setDrainMode(o);if(o.enabled&&o.waitForIdle&&u.drained===!1)return a.status(202).json(u);a.json(u)}catch(o){Ee(a,o)}}),e.get("/api/repos",async(s,a)=>{a.json(await n.listRepos())}),e.get("/api/repos/settings",async(s,a)=>{a.json(await n.listRepoSettings())}),e.post("/api/repos",async(s,a)=>{try{let{repo:o}=b.object({repo:b.string().min(1)}).parse(s.body);a.status(201).json(await n.addRepo(o))}catch(o){Ee(a,o)}}),e.patch("/api/repos/settings",async(s,a)=>{try{let o=b.object({repo:b.string().min(1),autoCreateReleases:b.boolean().optional(),ownPrsOnly:b.boolean().optional()}).refine(l=>l.autoCreateReleases!==void 0||l.ownPrsOnly!==void 0,"At least one repository setting must be provided").parse(s.body),{repo:u,...c}=o;a.json(await n.updateRepoSettings(u,c))}catch(o){Ee(a,o)}}),e.post("/api/repos/sync",async(s,a)=>{try{a.json(await n.syncRepos())}catch(o){Ee(a,o)}}),e.post("/api/repos/release",async(s,a)=>{try{let{repo:o}=b.object({repo:b.string().min(1)}).parse(s.body);a.status(201).json(await n.createManualRelease(o))}catch(o){Ee(a,o)}}),e.get("/api/prs",async(s,a)=>{a.json(await n.listPRs("active"))}),e.get("/api/prs/archived",async(s,a)=>{a.json(await n.listPRs("archived"))}),e.get("/api/prs/:id",async(s,a)=>{let o=await n.getPR(s.params.id);if(!o)return a.status(404).json({error:"PR not found"});a.json(o)}),e.post("/api/prs",async(s,a)=>{try{a.status(201).json(await n.addPR(s.body?.url))}catch(o){Ee(a,o)}}),e.delete("/api/prs/:id",async(s,a)=>{try{a.json(await n.removePR(s.params.id))}catch(o){Ee(a,o)}}),e.patch("/api/prs/:id/watch",async(s,a)=>{try{let{enabled:o}=b.object({enabled:b.boolean()}).parse(s.body);a.json(await n.setPRWatchEnabled(s.params.id,o))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/fetch",async(s,a)=>{try{a.json(await n.fetchPRFeedback(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/triage",async(s,a)=>{try{a.json(await n.triagePR(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/apply",async(s,a)=>{try{a.json(await n.applyPR(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/babysit",async(s,a)=>{try{a.json(await n.babysitPR(s.params.id))}catch(o){Ee(a,o)}}),e.patch("/api/prs/:id/feedback/:feedbackId",async(s,a)=>{try{let{decision:o}=b.object({decision:b.enum(["accept","reject","flag"])}).parse(s.body);a.json(await n.setFeedbackDecision(s.params.id,s.params.feedbackId,o))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/feedback/:feedbackId/retry",async(s,a)=>{try{a.json(await n.retryFeedback(s.params.id,s.params.feedbackId))}catch(o){Ee(a,o)}}),e.get("/api/prs/:id/questions",async(s,a)=>{try{a.json(await n.listPRQuestions(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/prs/:id/questions",async(s,a)=>{try{a.status(201).json(await n.askQuestion(s.params.id,s.body?.question))}catch(o){Ee(a,o)}}),e.get("/api/logs",async(s,a)=>{let o=typeof s.query.prId=="string"?s.query.prId:void 0;a.json(await n.listLogs(o))}),e.get("/api/onboarding/status",async(s,a)=>{try{a.json(await n.getOnboardingStatus())}catch(o){Ee(a,o)}}),e.post("/api/onboarding/install-review",async(s,a)=>{try{let{repo:o,tool:u}=b.object({repo:b.string().min(1),tool:b.enum(["claude","codex"])}).parse(s.body);a.json(await n.installReviewWorkflow(o,u))}catch(o){Ee(a,o)}}),e.get("/api/healing-sessions",async(s,a)=>{try{a.json(await n.listHealingSessions())}catch(o){Ee(a,o)}}),e.get("/api/healing-sessions/:id",async(s,a)=>{try{a.json(await n.getHealingSession(s.params.id))}catch(o){Ee(a,o)}}),e.get("/api/deployment-healing-sessions",async(s,a)=>{try{let o=typeof s.query.repo=="string"?s.query.repo:void 0;a.json(await n.listDeploymentHealingSessions(o))}catch(o){Ee(a,o)}}),e.get("/api/deployment-healing-sessions/:id",async(s,a)=>{try{a.json(await n.getDeploymentHealingSession(s.params.id))}catch(o){Ee(a,o)}}),e.get("/api/config",async(s,a)=>{a.json(q8(await n.getConfig()))}),e.get("/api/app-update",async(s,a)=>{try{a.json(await i("4.5.1"))}catch(o){Ee(a,o)}}),e.get("/api/changelogs",async(s,a)=>{try{a.json(await n.listSocialChangelogs())}catch(o){Ee(a,o)}}),e.get("/api/changelogs/:id",async(s,a)=>{try{a.json(await n.getSocialChangelog(s.params.id))}catch(o){Ee(a,o)}}),e.get("/api/releases",async(s,a)=>{try{a.json(await n.listReleaseRuns())}catch(o){Ee(a,o)}}),e.get("/api/releases/:id",async(s,a)=>{try{a.json(await n.getReleaseRun(s.params.id))}catch(o){Ee(a,o)}}),e.post("/api/releases/:id/retry",async(s,a)=>{try{a.json(await n.retryReleaseRun(s.params.id))}catch(o){Ee(a,o)}}),e.patch("/api/config",async(s,a)=>{try{let o=Il.partial().parse(s.body),u=await n.getConfig();a.json(q8(await n.updateConfig(Lne(u,o))))}catch(o){Ee(a,o)}}),t}var pO=je(wg(),1);var aO=require("node:net"),Ky=je(rO(),1),oO=require("node:net"),uO=require("node:buffer"),cO=require("node:crypto"),lO=require("node:net");function _ie(t,e=56){if((0,aO.isIPv6)(t)){let r=new Ky.Address6(t);if(r.is4())return r.to4().correctForm();if(e)return`${new Ky.Address6(`${t}/${e}`).startAddress().correctForm()}/${e}`}return t}var Eie=class{constructor(t){this.validations=t,this.previous=new Map,this.current=new Map,this.localKeys=!0}init(t){this.windowMs=t.windowMs,this.validations?.windowMs(this.windowMs),this.interval&&clearInterval(this.interval),this.interval=setInterval(()=>{this.clearExpired()},this.windowMs),this.interval.unref?.()}async get(t){return this.current.get(t)??this.previous.get(t)}async increment(t){let e=this.getClient(t),r=Date.now();return e.resetTime.getTime()<=r&&this.resetClient(e,r),e.totalHits++,e}async decrement(t){let e=this.getClient(t);e.totalHits>0&&e.totalHits--}async resetKey(t){this.current.delete(t),this.previous.delete(t)}async resetAll(){this.current.clear(),this.previous.clear()}shutdown(){clearInterval(this.interval),this.resetAll()}resetClient(t,e=Date.now()){return t.totalHits=0,t.resetTime.setTime(e+this.windowMs),t}getClient(t){if(this.current.has(t))return this.current.get(t);let e;return this.previous.has(t)?(e=this.previous.get(t),this.previous.delete(t)):(e={totalHits:0,resetTime:new Date},this.resetClient(e)),this.current.set(t,e),e}clearExpired(){this.previous=this.current,this.current=new Map}},Sie={warn(...t){console.warn(...t.reverse())},error(...t){console.error(...t.reverse())}},nO=["draft-6","draft-7","draft-8"],$d=(t,e)=>{let r;if(e){let n=Math.ceil((e.getTime()-Date.now())/1e3);r=Math.max(0,n)}else r=Math.ceil(t/1e3);return r},Tie=t=>{let e=(0,cO.createHash)("sha256");e.update(t);let r=e.digest("hex").slice(0,12);return uO.Buffer.from(r).toString("base64")},kie=(t,e)=>{t.headersSent||(t.setHeader("X-RateLimit-Limit",e.limit.toString()),t.setHeader("X-RateLimit-Remaining",e.remaining.toString()),e.resetTime instanceof Date&&(t.setHeader("Date",new Date().toUTCString()),t.setHeader("X-RateLimit-Reset",Math.ceil(e.resetTime.getTime()/1e3).toString())))},Rie=(t,e,r)=>{if(t.headersSent)return;let n=Math.ceil(r/1e3),i=$d(r,e.resetTime);t.setHeader("RateLimit-Policy",`${e.limit};w=${n}`),t.setHeader("RateLimit-Limit",e.limit.toString()),t.setHeader("RateLimit-Remaining",e.remaining.toString()),typeof i=="number"&&t.setHeader("RateLimit-Reset",i.toString())},Aie=(t,e,r)=>{if(t.headersSent)return;let n=Math.ceil(r/1e3),i=$d(r,e.resetTime);t.setHeader("RateLimit-Policy",`${e.limit};w=${n}`),t.setHeader("RateLimit",`limit=${e.limit}, remaining=${e.remaining}, reset=${i}`)},Pie=(t,e,r,n,i)=>{if(t.headersSent)return;let s=Math.ceil(r/1e3),a=$d(r,e.resetTime),o=Tie(i),u=`r=${e.remaining}; t=${a}`,c=`q=${e.limit}; w=${s}; pk=:${o}:`;t.append("RateLimit",`"${n}"; ${u}`),t.append("RateLimit-Policy",`"${n}"; ${c}`)},Cie=(t,e,r)=>{if(t.headersSent)return;let n=$d(r,e.resetTime);t.setHeader("Retry-After",n.toString())},Oie=t=>{let e={};for(let r of Object.keys(t)){let n=r;t[n]!==void 0&&(e[n]=t[n])}return e},nt=class extends Error{constructor(t,e){let r=`https://express-rate-limit.github.io/${t}/`;super(`${e} See ${r} for more information.`),this.name=this.constructor.name,this.code=t,this.help=r}},Gd=class extends nt{},iO=new Set,sO=new WeakMap,Iie={enabled:{default:!0},disable(){for(let t of Object.keys(this.enabled))this.enabled[t]=!1},ip(t){if(t===void 0)throw new nt("ERR_ERL_UNDEFINED_IP_ADDRESS","An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.");if(!(0,lO.isIP)(t))throw new nt("ERR_ERL_INVALID_IP_ADDRESS",`An invalid 'request.ip' (${t}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`)},trustProxy(t){if(t.app.get("trust proxy")===!0)throw new nt("ERR_ERL_PERMISSIVE_TRUST_PROXY","The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.")},xForwardedForHeader(t){if(t.headers["x-forwarded-for"]&&t.app.get("trust proxy")===!1)throw new nt("ERR_ERL_UNEXPECTED_X_FORWARDED_FOR","The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.")},forwardedHeader(t){if(t.headers.forwarded&&t.ip===t.socket?.remoteAddress)throw new nt("ERR_ERL_FORWARDED_HEADER","The 'Forwarded' header (standardized X-Forwarded-For) is set but currently being ignored. Add a custom keyGenerator to use a value from this header.")},positiveHits(t){if(typeof t!="number"||t<1||t!==Math.round(t))throw new nt("ERR_ERL_INVALID_HITS",`The totalHits value returned from the store must be a positive integer, got ${t}`)},unsharedStore(t){if(iO.has(t)){let e=t?.localKeys?"":" (with a unique prefix)";throw new nt("ERR_ERL_STORE_REUSE",`A Store instance must not be shared across multiple rate limiters. Create a new instance of ${t.constructor.name}${e} for each limiter instead.`)}iO.add(t)},singleCount(t,e,r){let n=sO.get(t);n||(n=new Map,sO.set(t,n));let i=e.localKeys?e:e.constructor.name,s=n.get(i);s||(s=[],n.set(i,s));let a=`${e.prefix??""}${r}`;if(s.includes(a))throw new nt("ERR_ERL_DOUBLE_COUNT",`The hit count for ${r} was incremented more than once for a single request.`);s.push(a)},limit(t){if(t===0)throw new Gd("WRN_ERL_MAX_ZERO","Setting limit or max to 0 disables rate limiting in express-rate-limit v6 and older, but will cause all requests to be blocked in v7")},draftPolliHeaders(t){if(t)throw new Gd("WRN_ERL_DEPRECATED_DRAFT_POLLI_HEADERS","The draft_polli_ratelimit_headers configuration option is deprecated and has been removed in express-rate-limit v7, please set standardHeaders: 'draft-6' instead.")},onLimitReached(t){if(t)throw new Gd("WRN_ERL_DEPRECATED_ON_LIMIT_REACHED","The onLimitReached configuration option is deprecated and has been removed in express-rate-limit v7.")},headersDraftVersion(t){if(typeof t!="string"||!nO.includes(t)){let e=nO.join(", ");throw new nt("ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION",`standardHeaders: only the following versions of the IETF draft specification are supported: ${e}.`)}},headersResetTime(t){if(!t)throw new nt("ERR_ERL_HEADERS_NO_RESET","standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.")},knownOptions(t){if(!t)return;let r=Object.keys({windowMs:!0,limit:!0,message:!0,statusCode:!0,legacyHeaders:!0,standardHeaders:!0,identifier:!0,requestPropertyName:!0,skipFailedRequests:!0,skipSuccessfulRequests:!0,keyGenerator:!0,ipv6Subnet:!0,handler:!0,skip:!0,requestWasSuccessful:!0,store:!0,validate:!0,headers:!0,max:!0,passOnStoreError:!0,logger:!0}).concat("draft_polli_ratelimit_headers","delayAfter","delayMs","maxDelayMs");for(let n of Object.keys(t))if(!r.includes(n))throw new nt("ERR_ERL_UNKNOWN_OPTION",`Unexpected configuration option: ${n}`)},validationsConfig(){let t=Object.keys(this).filter(e=>!["enabled","disable"].includes(e));t.push("default");for(let e of Object.keys(this.enabled))if(!t.includes(e))throw new nt("ERR_ERL_UNKNOWN_VALIDATION",`options.validate.${e} is not recognized. Supported validate options are: ${t.join(", ")}.`)},creationStack(t){let{stack:e}=new Error("express-rate-limit validation check (set options.validate.creationStack=false to disable)");if(e?.includes("Layer.handle [as handle_request]")||e?.includes("Layer.handleRequest"))throw t.localKeys?new nt("ERR_ERL_CREATED_IN_REQUEST_HANDLER","express-rate-limit instance should be created at app initialization, not when responding to a request."):new nt("ERR_ERL_CREATED_IN_REQUEST_HANDLER","express-rate-limit instance should *usually* be created at app initialization, not when responding to a request.")},ipv6Subnet(t){if(t!==!1&&(!Number.isInteger(t)||t<32||t>64))throw new nt("ERR_ERL_IPV6_SUBNET",`Unexpected ipv6Subnet value: ${t}. Expected an integer between 32 and 64 (usually 48-64).`)},ipv6SubnetOrKeyGenerator(t){if(t.ipv6Subnet!==void 0&&t.keyGenerator)throw new nt("ERR_ERL_IPV6SUBNET_OR_KEYGENERATOR","Incompatible options: the 'ipv6Subnet' option is ignored when a custom 'keyGenerator' function is also set.")},keyGeneratorIpFallback(t){if(!t)return;let e=t.toString();if((e.includes("req.ip")||e.includes("request.ip"))&&!e.includes("ipKeyGenerator"))throw new nt("ERR_ERL_KEY_GEN_IPV6","Custom keyGenerator appears to use request IP without calling the ipKeyGenerator helper function for IPv6 addresses. This could allow IPv6 users to bypass limits.")},windowMs(t){if(typeof t!="number"||Number.isNaN(t)||t<1||t>2147483647)throw new nt("ERR_ERL_WINDOW_MS",`Invalid windowMs value: ${t}${typeof t!="number"?` (${typeof t})`:""}, must be a number between 1 and 2147483647 when using the default MemoryStore`)}};function Lie(t){if(typeof t!="object"||typeof t.error!="function"||typeof t.warn!="function")throw new TypeError("Provided logger does not implement the Logger interface")}var Die=(t,e)=>{Lie(e);let r;typeof t=="boolean"?r={default:t}:r={default:!0,...t};let n={enabled:r};for(let[i,s]of Object.entries(Iie))typeof s=="function"&&(n[i]=(...a)=>{if(r[i]??r.default)try{s.apply(n,a)}catch(o){o instanceof Gd?e.warn(o):e.error(o)}});return n},Nie=t=>typeof t.incr=="function"&&typeof t.increment!="function",Fie=t=>{if(!Nie(t))return t;let e=t;class r{async increment(i){return new Promise((s,a)=>{e.incr(i,(o,u,c)=>{o&&a(o),s({totalHits:u,resetTime:c})})})}async decrement(i){return e.decrement(i)}async resetKey(i){return e.resetKey(i)}async resetAll(){if(typeof e.resetAll=="function")return e.resetAll()}}return new r},Mie=t=>{let{validations:e,...r}=t;return{...r,validate:e.enabled}},jie=t=>{let e=Oie(t),r=t.logger??Sie,n=Die(e?.validate??!0,r);n.validationsConfig(),n.knownOptions(t),n.draftPolliHeaders(e.draft_polli_ratelimit_headers),n.onLimitReached(e.onLimitReached),e.ipv6Subnet!==void 0&&typeof e.ipv6Subnet!="function"&&n.ipv6Subnet(e.ipv6Subnet),n.keyGeneratorIpFallback(e.keyGenerator),n.ipv6SubnetOrKeyGenerator(e);let i=e.standardHeaders??!1;i===!0&&(i="draft-6");let s={windowMs:60*1e3,limit:t.max??5,message:"Too many requests, please try again later.",statusCode:429,legacyHeaders:t.headers??!0,identifier(a,o){let u="",c=s.requestPropertyName,{limit:l}=a[c],d=s.windowMs/1e3,p=s.windowMs/(1e3*60),m=s.windowMs/(1e3*60*60),f=s.windowMs/(1e3*60*60*24);return d<60?u=`${d}sec`:p<60?u=`${p}min`:m<24?u=`${m}hr${m>1?"s":""}`:u=`${f}day${f>1?"s":""}`,`${l}-in-${u}`},requestPropertyName:"rateLimit",skipFailedRequests:!1,skipSuccessfulRequests:!1,requestWasSuccessful:(a,o)=>o.statusCode<400,skip:(a,o)=>!1,async keyGenerator(a,o){n.ip(a.ip),n.trustProxy(a),n.xForwardedForHeader(a),n.forwardedHeader(a);let u=a.ip,c=56;return(0,oO.isIPv6)(u)&&(c=typeof s.ipv6Subnet=="function"?await s.ipv6Subnet(a,o):s.ipv6Subnet,typeof s.ipv6Subnet=="function"&&n.ipv6Subnet(c)),_ie(u,c)},ipv6Subnet:56,async handler(a,o,u,c){o.status(s.statusCode);let l=typeof s.message=="function"?await s.message(a,o):s.message;o.writableEnded||o.send(l)},passOnStoreError:!1,...e,standardHeaders:i,store:Fie(e.store??new Eie(n)),validations:n,logger:r};if(typeof s.store.increment!="function"||typeof s.store.decrement!="function"||typeof s.store.resetKey!="function"||s.store.resetAll!==void 0&&typeof s.store.resetAll!="function"||s.store.init!==void 0&&typeof s.store.init!="function")throw new TypeError("An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.");return s},Bie=t=>async(e,r,n)=>{try{await Promise.resolve(t(e,r,n)).catch(n)}catch(i){n(i)}},Uie=t=>{let e=jie(t??{}),r=Mie(e);if(e.validations.creationStack(e.store),e.validations.unsharedStore(e.store),typeof e.store.init=="function")try{let s=e.store.init(r);s instanceof Promise&&s.catch(a=>e.logger.error(a,"express-rate-limit: async error during store initialization."))}catch(s){e.logger.error(s,"express-rate-limit: error during store initialization.")}let n=Bie(async(s,a,o)=>{let u=e.skipFailedRequests&&new Promise(S=>a.once("close",S)),c=(e.skipFailedRequests||e.skipSuccessfulRequests)&&new Promise(S=>a.once("finish",S)),l=e.skipFailedRequests&&new Promise(S=>a.once("error",S));if(await e.skip(s,a)){o();return}let p=s,m=await e.keyGenerator(s,a),f=0,g;try{let S=await e.store.increment(m);f=S.totalHits,g=S.resetTime}catch(S){if(e.passOnStoreError){e.logger.error(S,"express-rate-limit: error from store, allowing request without rate-limiting."),o();return}throw S}e.validations.positiveHits(f),e.validations.singleCount(s,e.store,m);let _=await(typeof e.limit=="function"?e.limit(s,a):e.limit);e.validations.limit(_);let k={limit:_,used:f,remaining:Math.max(_-f,0),resetTime:g,key:m};if(Object.defineProperty(k,"current",{configurable:!1,enumerable:!1,value:f}),p[e.requestPropertyName]=k,e.legacyHeaders&&!a.headersSent&&kie(a,k),e.standardHeaders&&!a.headersSent)switch(e.standardHeaders){case"draft-6":{Rie(a,k,e.windowMs);break}case"draft-7":{e.validations.headersResetTime(k.resetTime),Aie(a,k,e.windowMs);break}case"draft-8":{let C=await(typeof e.identifier=="function"?e.identifier(s,a):e.identifier);e.validations.headersResetTime(k.resetTime),Pie(a,k,e.windowMs,C,m);break}default:{e.validations.headersDraftVersion(e.standardHeaders);break}}if(e.skipFailedRequests||e.skipSuccessfulRequests){let S=!1,C=async()=>{S||(await e.store.decrement(m),S=!0)};e.skipFailedRequests&&(c&&c.then(async()=>{await e.requestWasSuccessful(s,a)||await C()}),u&&u.then(async()=>{a.writableEnded||await C()}),l&&l.then(async()=>{await C()})),e.skipSuccessfulRequests&&c&&c.then(async()=>{await e.requestWasSuccessful(s,a)&&await C()})}if(e.validations.disable(),f>_){(e.legacyHeaders||e.standardHeaders)&&Cie(a,k,e.windowMs),e.handler(s,a,o,r);return}o()}),i=()=>{throw new Error("The current store does not support the get/getKey method")};return n.resetKey=e.store.resetKey.bind(e.store),n.getKey=typeof e.store.get=="function"?e.store.get.bind(e.store):i,n},Hd=Uie;var dO=je(require("fs"),1),Xy=je(require("path"),1),fO=require("url"),$ie={},qie=Hd({windowMs:60*1e3,limit:600,standardHeaders:!0,legacyHeaders:!1});function Gie(){return typeof __dirname=="string"?__dirname:Xy.default.dirname((0,fO.fileURLToPath)($ie.url))}function mO(t,e=Gie()){let r=Xy.default.resolve(e,"public");if(!dO.default.existsSync(r))throw new Error(`Could not find the build directory: ${r}, make sure to build the client first`);t.use(pO.default.static(r)),t.use("/{*path}",qie,(n,i)=>{i.sendFile("index.html",{root:r})})}var pc=je(require("node:crypto"),1),bv=je(eI(),1),SI=je(bI(),1);var iae=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function yI(t){if(!t)return!1;let e=t.replace(/^\[|\]$/g,"");return iae.has(e)?!0:e.startsWith("::ffff:")?e.slice(7).startsWith("127."):!!e.startsWith("127.")}var gv="OH_MY_PR_WEB_USERNAME",hv="OH_MY_PR_WEB_PASSWORD",sae="OH_MY_PR_SESSION_SECRET",vI="oh-my-pr.sid",wI=720*60*1e3,aae=(0,SI.default)(bv.default);function xI(t){let e=t?.trim();return e||void 0}function oae(t=process.env){return{username:xI(t[gv]),password:t[hv],sessionSecret:xI(t[sae])}}function uae(t){return!t.username||!t.password?null:{username:t.username,password:t.password}}function cae(t){return t.ip??t.socket?.remoteAddress}function TI(t){return yI(cae(t))}function _I(t,e){let r=pc.default.createHash("sha256").update(t).digest(),n=pc.default.createHash("sha256").update(e).digest();return pc.default.timingSafeEqual(r,n)}function mv(t,e){let r=!TI(t),n=t.session?.authenticatedWebUser??null,i=!r||!!(e&&n===e.username);return{requiresLogin:r,loginConfigured:e!==null,authenticated:i,username:i&&e?e.username:null}}function lae(t){return new Promise((e,r)=>{t.session.regenerate(n=>{if(n){r(n);return}e()})})}function pae(t){return new Promise((e,r)=>{t.session.save(n=>{if(n){r(n);return}e()})})}function dae(t){return new Promise((e,r)=>{t.session.destroy(n=>{if(n){r(n);return}e()})})}function EI(t,e){let r=e instanceof Error?e.message:String(e);return new Error(`Web auth ${t} failed: ${r}`,{cause:e})}function kI(t,e=oae()){let r=uae(e),n=e.sessionSecret??pc.default.randomBytes(32).toString("hex");t.use((0,bv.default)({name:vI,secret:n,store:new aae({checkPeriod:wI}),resave:!1,saveUninitialized:!1,cookie:{httpOnly:!0,sameSite:"lax",secure:!0,maxAge:wI}}));let i=Hd({windowMs:300*1e3,limit:20,standardHeaders:!0,legacyHeaders:!1});return t.get("/api/auth/status",(s,a)=>{a.json(mv(s,r))}),t.post("/api/auth/login",i,async(s,a,o)=>{if(!r){a.status(403).json({error:"Remote login is not configured",message:`Set ${gv} and ${hv} before using remote web access.`});return}let u=typeof s.body?.username=="string"?s.body.username:"",c=typeof s.body?.password=="string"?s.body.password:"";if(!_I(u,r.username)||!_I(c,r.password)){a.status(401).json({error:"Invalid credentials",message:"Username or password is incorrect."});return}let l="session regeneration";try{await lae(s),s.session.authenticatedWebUser=r.username,l="session save",await pae(s)}catch(d){o(EI(l,d));return}a.json(mv(s,r))}),t.post("/api/auth/logout",async(s,a,o)=>{try{s.session.authenticatedWebUser&&(await dae(s),a.clearCookie(vI))}catch(u){o(EI("session destroy",u));return}a.json(mv(s,r))}),{apiAccessMiddleware(s,a,o){if(TI(s)){o();return}if(!r){a.status(403).json({error:"Remote access is not configured",message:`Set ${gv} and ${hv} to allow remote dashboard login.`});return}if(s.session?.authenticatedWebUser===r.username){o();return}a.status(401).json({error:"Login required",message:"Sign in to use oh-my-pr from this network address."})}}}var AI=require("http");var fae=lr("server"),Ln=(0,Xd.default)(),RI=(0,AI.createServer)(Ln);function mae(t){let e=t?.trim();if(!e||e==="false")return!1;if(e==="true")return!0;let r=Number(e);return Number.isInteger(r)&&r>=0?r:e}Ln.use(Xd.default.json({verify:(t,e,r)=>{t.rawBody=r}}));Ln.use(Xd.default.urlencoded({extended:!1}));Ln.set("trust proxy",mae(process.env.OH_MY_PR_TRUST_PROXY));var gae=kI(Ln);Ln.use("/api",gae.apiAccessMiddleware);function PI(t,e="express"){V0.info({source:e},t)}async function hae(t){let{default:e}=await import("open");await e(t)}(async()=>{await H8(RI,Ln),Ln.use((e,r,n,i)=>{let s=e,a=s.status||s.statusCode||500,o=s.message||"Internal Server Error";return fae.error({err:e instanceof Error?e.message:String(e),status:a},"Internal Server Error"),n.headersSent?i(e):n.status(a).json({message:o})}),mO(Ln);let t=parseInt(process.env.PORT||"5001",10);RI.listen({port:t,host:"0.0.0.0"},()=>{let e=`http://localhost:${t}`;console.log(`
1112
+ oh-my-pr v4.5.1
1113
1113
  Dashboard: ${e}
1114
1114
  `),!process.env.TAURI_DEV&&!process.env.OH_MY_PR_DESKTOP&&hae(e).catch(n=>{PI(`Could not open browser automatically: ${n.message}`)})})})();0&&(module.exports={log});
1115
1115
  /*! Bundled license information: