oh-my-pr 4.5.3 → 4.5.4

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
@@ -1109,8 +1109,8 @@ data: ${JSON.stringify(e)}
1109
1109
 
1110
1110
  `)!==!1}function jne(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:Fne(t.githubTokens,r)}}function G8(t){let e=t.githubTokens.map(z8);return{...t,githubTokens:e,githubToken:e[0]??""}}async function W8(t,e,r={}){let n=r.runtime??B8(r),i=r.appUpdateChecker??$8();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=J0({level:Dne(s.query.level),source:typeof s.query.source=="string"?s.query.source:void 0,since:Ld(s.query.since),search:typeof s.query.search=="string"?s.query.search:void 0,limit:Ld(s.query.limit)??500});a.json({records:o,sources:gP(),latestSeq:o.length>0?o[o.length-1].seq:Ld(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()}
1111
1111
 
1112
- `)===!1&&l()},2e4),l=()=>{o||(o=!0,clearInterval(c),u(),a.writableEnded||a.end())},d=f=>{Mne(a,f)||l()},p=Ld(s.query.since);if(p!==void 0){let f=J0({since:p,limit:1e3});for(let m of f)if(d(m),o)return}u=hP(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=y.object({enabled:y.boolean(),reason:y.string().optional(),waitForIdle:y.boolean().optional(),timeoutMs:y.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}=y.object({repo:y.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=y.object({repo:y.string().min(1),autoCreateReleases:y.boolean().optional(),ownPrsOnly:y.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}=y.object({repo:y.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}=y.object({enabled:y.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}=y.object({decision:y.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}=y.object({repo:y.string().min(1),tool:y.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(G8(await n.getConfig()))}),e.get("/api/app-update",async(s,a)=>{try{a.json(await i("4.5.3"))}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(G8(await n.updateConfig(jne(u,o))))}catch(o){Ee(a,o)}}),t}var fO=Me(_g(),1);var uO=require("node:net"),Yy=Me(iO(),1),cO=require("node:net"),lO=require("node:buffer"),pO=require("node:crypto"),dO=require("node:net");function Rie(t,e=56){if((0,uO.isIPv6)(t)){let r=new Yy.Address6(t);if(r.is4())return r.to4().correctForm();if(e)return`${new Yy.Address6(`${t}/${e}`).startAddress().correctForm()}/${e}`}return t}var Aie=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}},Pie={warn(...t){console.warn(...t.reverse())},error(...t){console.error(...t.reverse())}},sO=["draft-6","draft-7","draft-8"],Hd=(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},Cie=t=>{let e=(0,pO.createHash)("sha256");e.update(t);let r=e.digest("hex").slice(0,12);return lO.Buffer.from(r).toString("base64")},Oie=(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())))},Iie=(t,e,r)=>{if(t.headersSent)return;let n=Math.ceil(r/1e3),i=Hd(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())},Lie=(t,e,r)=>{if(t.headersSent)return;let n=Math.ceil(r/1e3),i=Hd(r,e.resetTime);t.setHeader("RateLimit-Policy",`${e.limit};w=${n}`),t.setHeader("RateLimit",`limit=${e.limit}, remaining=${e.remaining}, reset=${i}`)},Die=(t,e,r,n,i)=>{if(t.headersSent)return;let s=Math.ceil(r/1e3),a=Hd(r,e.resetTime),o=Cie(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}`)},Nie=(t,e,r)=>{if(t.headersSent)return;let n=Hd(r,e.resetTime);t.setHeader("Retry-After",n.toString())},Fie=t=>{let e={};for(let r of Object.keys(t)){let n=r;t[n]!==void 0&&(e[n]=t[n])}return e},it=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 it{},aO=new Set,oO=new WeakMap,Mie={enabled:{default:!0},disable(){for(let t of Object.keys(this.enabled))this.enabled[t]=!1},ip(t){if(t===void 0)throw new it("ERR_ERL_UNDEFINED_IP_ADDRESS","An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.");if(!(0,dO.isIP)(t))throw new it("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 it("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 it("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 it("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 it("ERR_ERL_INVALID_HITS",`The totalHits value returned from the store must be a positive integer, got ${t}`)},unsharedStore(t){if(aO.has(t)){let e=t?.localKeys?"":" (with a unique prefix)";throw new it("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.`)}aO.add(t)},singleCount(t,e,r){let n=oO.get(t);n||(n=new Map,oO.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 it("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"||!sO.includes(t)){let e=sO.join(", ");throw new it("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 it("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 it("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 it("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 it("ERR_ERL_CREATED_IN_REQUEST_HANDLER","express-rate-limit instance should be created at app initialization, not when responding to a request."):new it("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 it("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 it("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 it("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 it("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 jie(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 Bie=(t,e)=>{jie(e);let r;typeof t=="boolean"?r={default:t}:r={default:!0,...t};let n={enabled:r};for(let[i,s]of Object.entries(Mie))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},Uie=t=>typeof t.incr=="function"&&typeof t.increment!="function",qie=t=>{if(!Uie(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},$ie=t=>{let{validations:e,...r}=t;return{...r,validate:e.enabled}},Gie=t=>{let e=Fie(t),r=t.logger??Pie,n=Bie(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),f=s.windowMs/(1e3*60*60),m=s.windowMs/(1e3*60*60*24);return d<60?u=`${d}sec`:p<60?u=`${p}min`:f<24?u=`${f}hr${f>1?"s":""}`:u=`${m}day${m>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,cO.isIPv6)(u)&&(c=typeof s.ipv6Subnet=="function"?await s.ipv6Subnet(a,o):s.ipv6Subnet,typeof s.ipv6Subnet=="function"&&n.ipv6Subnet(c)),Rie(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:qie(e.store??new Aie(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},Hie=t=>async(e,r,n)=>{try{await Promise.resolve(t(e,r,n)).catch(n)}catch(i){n(i)}},zie=t=>{let e=Gie(t??{}),r=$ie(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=Hie(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,f=await e.keyGenerator(s,a),m=0,h;try{let S=await e.store.increment(f);m=S.totalHits,h=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(m),e.validations.singleCount(s,e.store,f);let E=await(typeof e.limit=="function"?e.limit(s,a):e.limit);e.validations.limit(E);let R={limit:E,used:m,remaining:Math.max(E-m,0),resetTime:h,key:f};if(Object.defineProperty(R,"current",{configurable:!1,enumerable:!1,value:m}),p[e.requestPropertyName]=R,e.legacyHeaders&&!a.headersSent&&Oie(a,R),e.standardHeaders&&!a.headersSent)switch(e.standardHeaders){case"draft-6":{Iie(a,R,e.windowMs);break}case"draft-7":{e.validations.headersResetTime(R.resetTime),Lie(a,R,e.windowMs);break}case"draft-8":{let P=await(typeof e.identifier=="function"?e.identifier(s,a):e.identifier);e.validations.headersResetTime(R.resetTime),Die(a,R,e.windowMs,P,f);break}default:{e.validations.headersDraftVersion(e.standardHeaders);break}}if(e.skipFailedRequests||e.skipSuccessfulRequests){let S=!1,P=async()=>{S||(await e.store.decrement(f),S=!0)};e.skipFailedRequests&&(c&&c.then(async()=>{await e.requestWasSuccessful(s,a)||await P()}),u&&u.then(async()=>{a.writableEnded||await P()}),l&&l.then(async()=>{await P()})),e.skipSuccessfulRequests&&c&&c.then(async()=>{await e.requestWasSuccessful(s,a)&&await P()})}if(e.validations.disable(),m>E){(e.legacyHeaders||e.standardHeaders)&&Nie(a,R,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},zd=zie;var mO=Me(require("fs"),1),Qy=Me(require("path"),1),gO=require("url"),Jie={},Wie=zd({windowMs:60*1e3,limit:600,standardHeaders:!0,legacyHeaders:!1});function Vie(){return typeof __dirname=="string"?__dirname:Qy.default.dirname((0,gO.fileURLToPath)(Jie.url))}function hO(t,e=Vie()){let r=Qy.default.resolve(e,"public");if(!mO.default.existsSync(r))throw new Error(`Could not find the build directory: ${r}, make sure to build the client first`);t.use(fO.default.static(r)),t.use("/{*path}",Wie,(n,i)=>{i.sendFile("index.html",{root:r})})}var pc=Me(require("node:crypto"),1),vv=Me(rI(),1),kI=Me(vI(),1);var cae=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function wI(t){if(!t)return!1;let e=t.replace(/^\[|\]$/g,"");return cae.has(e)?!0:e.startsWith("::ffff:")?e.slice(7).startsWith("127."):!!e.startsWith("127.")}var bv="OH_MY_PR_WEB_USERNAME",yv="OH_MY_PR_WEB_PASSWORD",lae="OH_MY_PR_SESSION_SECRET",xI="oh-my-pr.sid",_I=720*60*1e3,pae=(0,kI.default)(vv.default);function EI(t){let e=t?.trim();return e||void 0}function dae(t=process.env){return{username:EI(t[bv]),password:t[yv],sessionSecret:EI(t[lae])}}function fae(t){return!t.username||!t.password?null:{username:t.username,password:t.password}}function mae(t){return t.ip??t.socket?.remoteAddress}function RI(t){return wI(mae(t))}function SI(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 hv(t,e){let r=!RI(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 gae(t){return new Promise((e,r)=>{t.session.regenerate(n=>{if(n){r(n);return}e()})})}function hae(t){return new Promise((e,r)=>{t.session.save(n=>{if(n){r(n);return}e()})})}function bae(t){return new Promise((e,r)=>{t.session.destroy(n=>{if(n){r(n);return}e()})})}function TI(t,e){let r=e instanceof Error?e.message:String(e);return new Error(`Web auth ${t} failed: ${r}`,{cause:e})}function AI(t,e=dae()){let r=fae(e),n=e.sessionSecret??pc.default.randomBytes(32).toString("hex");t.use((0,vv.default)({name:xI,secret:n,store:new pae({checkPeriod:_I}),resave:!1,saveUninitialized:!1,cookie:{httpOnly:!0,sameSite:"lax",secure:!0,maxAge:_I}}));let i=zd({windowMs:300*1e3,limit:20,standardHeaders:!0,legacyHeaders:!1});return t.get("/api/auth/status",(s,a)=>{a.json(hv(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 ${bv} and ${yv} 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(!SI(u,r.username)||!SI(c,r.password)){a.status(401).json({error:"Invalid credentials",message:"Username or password is incorrect."});return}let l="session regeneration";try{await gae(s),s.session.authenticatedWebUser=r.username,l="session save",await hae(s)}catch(d){o(TI(l,d));return}a.json(hv(s,r))}),t.post("/api/auth/logout",async(s,a,o)=>{try{s.session.authenticatedWebUser&&(await bae(s),a.clearCookie(xI))}catch(u){o(TI("session destroy",u));return}a.json(hv(s,r))}),{apiAccessMiddleware(s,a,o){if(RI(s)){o();return}if(!r){a.status(403).json({error:"Remote access is not configured",message:`Set ${bv} and ${yv} 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 CI=require("http");var yae=lr("server"),Dn=(0,Yd.default)(),PI=(0,CI.createServer)(Dn);function vae(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}Dn.use(Yd.default.json({verify:(t,e,r)=>{t.rawBody=r}}));Dn.use(Yd.default.urlencoded({extended:!1}));Dn.set("trust proxy",vae(process.env.OH_MY_PR_TRUST_PROXY));var wae=AI(Dn);Dn.use("/api",wae.apiAccessMiddleware);function OI(t,e="express"){K0.info({source:e},t)}async function xae(t){let{default:e}=await import("open");await e(t)}(async()=>{await W8(PI,Dn),Dn.use((e,r,n,i)=>{let s=e,a=s.status||s.statusCode||500,o=s.message||"Internal Server Error";return yae.error({err:e instanceof Error?e.message:String(e),status:a},"Internal Server Error"),n.headersSent?i(e):n.status(a).json({message:o})}),hO(Dn);let t=parseInt(process.env.PORT||"5001",10);PI.listen({port:t,host:"0.0.0.0"},()=>{let e=`http://localhost:${t}`;console.log(`
1113
- oh-my-pr v4.5.3
1112
+ `)===!1&&l()},2e4),l=()=>{o||(o=!0,clearInterval(c),u(),a.writableEnded||a.end())},d=f=>{Mne(a,f)||l()},p=Ld(s.query.since);if(p!==void 0){let f=J0({since:p,limit:1e3});for(let m of f)if(d(m),o)return}u=hP(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=y.object({enabled:y.boolean(),reason:y.string().optional(),waitForIdle:y.boolean().optional(),timeoutMs:y.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}=y.object({repo:y.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=y.object({repo:y.string().min(1),autoCreateReleases:y.boolean().optional(),ownPrsOnly:y.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}=y.object({repo:y.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}=y.object({enabled:y.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}=y.object({decision:y.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}=y.object({repo:y.string().min(1),tool:y.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(G8(await n.getConfig()))}),e.get("/api/app-update",async(s,a)=>{try{a.json(await i("4.5.4"))}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(G8(await n.updateConfig(jne(u,o))))}catch(o){Ee(a,o)}}),t}var fO=Me(_g(),1);var uO=require("node:net"),Yy=Me(iO(),1),cO=require("node:net"),lO=require("node:buffer"),pO=require("node:crypto"),dO=require("node:net");function Rie(t,e=56){if((0,uO.isIPv6)(t)){let r=new Yy.Address6(t);if(r.is4())return r.to4().correctForm();if(e)return`${new Yy.Address6(`${t}/${e}`).startAddress().correctForm()}/${e}`}return t}var Aie=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}},Pie={warn(...t){console.warn(...t.reverse())},error(...t){console.error(...t.reverse())}},sO=["draft-6","draft-7","draft-8"],Hd=(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},Cie=t=>{let e=(0,pO.createHash)("sha256");e.update(t);let r=e.digest("hex").slice(0,12);return lO.Buffer.from(r).toString("base64")},Oie=(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())))},Iie=(t,e,r)=>{if(t.headersSent)return;let n=Math.ceil(r/1e3),i=Hd(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())},Lie=(t,e,r)=>{if(t.headersSent)return;let n=Math.ceil(r/1e3),i=Hd(r,e.resetTime);t.setHeader("RateLimit-Policy",`${e.limit};w=${n}`),t.setHeader("RateLimit",`limit=${e.limit}, remaining=${e.remaining}, reset=${i}`)},Die=(t,e,r,n,i)=>{if(t.headersSent)return;let s=Math.ceil(r/1e3),a=Hd(r,e.resetTime),o=Cie(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}`)},Nie=(t,e,r)=>{if(t.headersSent)return;let n=Hd(r,e.resetTime);t.setHeader("Retry-After",n.toString())},Fie=t=>{let e={};for(let r of Object.keys(t)){let n=r;t[n]!==void 0&&(e[n]=t[n])}return e},it=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 it{},aO=new Set,oO=new WeakMap,Mie={enabled:{default:!0},disable(){for(let t of Object.keys(this.enabled))this.enabled[t]=!1},ip(t){if(t===void 0)throw new it("ERR_ERL_UNDEFINED_IP_ADDRESS","An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.");if(!(0,dO.isIP)(t))throw new it("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 it("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 it("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 it("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 it("ERR_ERL_INVALID_HITS",`The totalHits value returned from the store must be a positive integer, got ${t}`)},unsharedStore(t){if(aO.has(t)){let e=t?.localKeys?"":" (with a unique prefix)";throw new it("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.`)}aO.add(t)},singleCount(t,e,r){let n=oO.get(t);n||(n=new Map,oO.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 it("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"||!sO.includes(t)){let e=sO.join(", ");throw new it("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 it("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 it("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 it("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 it("ERR_ERL_CREATED_IN_REQUEST_HANDLER","express-rate-limit instance should be created at app initialization, not when responding to a request."):new it("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 it("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 it("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 it("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 it("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 jie(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 Bie=(t,e)=>{jie(e);let r;typeof t=="boolean"?r={default:t}:r={default:!0,...t};let n={enabled:r};for(let[i,s]of Object.entries(Mie))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},Uie=t=>typeof t.incr=="function"&&typeof t.increment!="function",qie=t=>{if(!Uie(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},$ie=t=>{let{validations:e,...r}=t;return{...r,validate:e.enabled}},Gie=t=>{let e=Fie(t),r=t.logger??Pie,n=Bie(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),f=s.windowMs/(1e3*60*60),m=s.windowMs/(1e3*60*60*24);return d<60?u=`${d}sec`:p<60?u=`${p}min`:f<24?u=`${f}hr${f>1?"s":""}`:u=`${m}day${m>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,cO.isIPv6)(u)&&(c=typeof s.ipv6Subnet=="function"?await s.ipv6Subnet(a,o):s.ipv6Subnet,typeof s.ipv6Subnet=="function"&&n.ipv6Subnet(c)),Rie(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:qie(e.store??new Aie(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},Hie=t=>async(e,r,n)=>{try{await Promise.resolve(t(e,r,n)).catch(n)}catch(i){n(i)}},zie=t=>{let e=Gie(t??{}),r=$ie(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=Hie(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,f=await e.keyGenerator(s,a),m=0,h;try{let S=await e.store.increment(f);m=S.totalHits,h=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(m),e.validations.singleCount(s,e.store,f);let E=await(typeof e.limit=="function"?e.limit(s,a):e.limit);e.validations.limit(E);let R={limit:E,used:m,remaining:Math.max(E-m,0),resetTime:h,key:f};if(Object.defineProperty(R,"current",{configurable:!1,enumerable:!1,value:m}),p[e.requestPropertyName]=R,e.legacyHeaders&&!a.headersSent&&Oie(a,R),e.standardHeaders&&!a.headersSent)switch(e.standardHeaders){case"draft-6":{Iie(a,R,e.windowMs);break}case"draft-7":{e.validations.headersResetTime(R.resetTime),Lie(a,R,e.windowMs);break}case"draft-8":{let P=await(typeof e.identifier=="function"?e.identifier(s,a):e.identifier);e.validations.headersResetTime(R.resetTime),Die(a,R,e.windowMs,P,f);break}default:{e.validations.headersDraftVersion(e.standardHeaders);break}}if(e.skipFailedRequests||e.skipSuccessfulRequests){let S=!1,P=async()=>{S||(await e.store.decrement(f),S=!0)};e.skipFailedRequests&&(c&&c.then(async()=>{await e.requestWasSuccessful(s,a)||await P()}),u&&u.then(async()=>{a.writableEnded||await P()}),l&&l.then(async()=>{await P()})),e.skipSuccessfulRequests&&c&&c.then(async()=>{await e.requestWasSuccessful(s,a)&&await P()})}if(e.validations.disable(),m>E){(e.legacyHeaders||e.standardHeaders)&&Nie(a,R,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},zd=zie;var mO=Me(require("fs"),1),Qy=Me(require("path"),1),gO=require("url"),Jie={},Wie=zd({windowMs:60*1e3,limit:600,standardHeaders:!0,legacyHeaders:!1});function Vie(){return typeof __dirname=="string"?__dirname:Qy.default.dirname((0,gO.fileURLToPath)(Jie.url))}function hO(t,e=Vie()){let r=Qy.default.resolve(e,"public");if(!mO.default.existsSync(r))throw new Error(`Could not find the build directory: ${r}, make sure to build the client first`);t.use(fO.default.static(r)),t.use("/{*path}",Wie,(n,i)=>{i.sendFile("index.html",{root:r})})}var pc=Me(require("node:crypto"),1),vv=Me(rI(),1),kI=Me(vI(),1);var cae=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function wI(t){if(!t)return!1;let e=t.replace(/^\[|\]$/g,"");return cae.has(e)?!0:e.startsWith("::ffff:")?e.slice(7).startsWith("127."):!!e.startsWith("127.")}var bv="OH_MY_PR_WEB_USERNAME",yv="OH_MY_PR_WEB_PASSWORD",lae="OH_MY_PR_SESSION_SECRET",xI="oh-my-pr.sid",_I=720*60*1e3,pae=(0,kI.default)(vv.default);function EI(t){let e=t?.trim();return e||void 0}function dae(t=process.env){return{username:EI(t[bv]),password:t[yv],sessionSecret:EI(t[lae])}}function fae(t){return!t.username||!t.password?null:{username:t.username,password:t.password}}function mae(t){return t.ip??t.socket?.remoteAddress}function RI(t){return wI(mae(t))}function SI(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 hv(t,e){let r=!RI(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 gae(t){return new Promise((e,r)=>{t.session.regenerate(n=>{if(n){r(n);return}e()})})}function hae(t){return new Promise((e,r)=>{t.session.save(n=>{if(n){r(n);return}e()})})}function bae(t){return new Promise((e,r)=>{t.session.destroy(n=>{if(n){r(n);return}e()})})}function TI(t,e){let r=e instanceof Error?e.message:String(e);return new Error(`Web auth ${t} failed: ${r}`,{cause:e})}function AI(t,e=dae()){let r=fae(e),n=e.sessionSecret??pc.default.randomBytes(32).toString("hex");t.use((0,vv.default)({name:xI,secret:n,store:new pae({checkPeriod:_I}),resave:!1,saveUninitialized:!1,cookie:{httpOnly:!0,sameSite:"lax",secure:!0,maxAge:_I}}));let i=zd({windowMs:300*1e3,limit:20,standardHeaders:!0,legacyHeaders:!1});return t.get("/api/auth/status",(s,a)=>{a.json(hv(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 ${bv} and ${yv} 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(!SI(u,r.username)||!SI(c,r.password)){a.status(401).json({error:"Invalid credentials",message:"Username or password is incorrect."});return}let l="session regeneration";try{await gae(s),s.session.authenticatedWebUser=r.username,l="session save",await hae(s)}catch(d){o(TI(l,d));return}a.json(hv(s,r))}),t.post("/api/auth/logout",async(s,a,o)=>{try{s.session.authenticatedWebUser&&(await bae(s),a.clearCookie(xI))}catch(u){o(TI("session destroy",u));return}a.json(hv(s,r))}),{apiAccessMiddleware(s,a,o){if(RI(s)){o();return}if(!r){a.status(403).json({error:"Remote access is not configured",message:`Set ${bv} and ${yv} 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 CI=require("http");var yae=lr("server"),Dn=(0,Yd.default)(),PI=(0,CI.createServer)(Dn);function vae(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}Dn.use(Yd.default.json({verify:(t,e,r)=>{t.rawBody=r}}));Dn.use(Yd.default.urlencoded({extended:!1}));Dn.set("trust proxy",vae(process.env.OH_MY_PR_TRUST_PROXY));var wae=AI(Dn);Dn.use("/api",wae.apiAccessMiddleware);function OI(t,e="express"){K0.info({source:e},t)}async function xae(t){let{default:e}=await import("open");await e(t)}(async()=>{await W8(PI,Dn),Dn.use((e,r,n,i)=>{let s=e,a=s.status||s.statusCode||500,o=s.message||"Internal Server Error";return yae.error({err:e instanceof Error?e.message:String(e),status:a},"Internal Server Error"),n.headersSent?i(e):n.status(a).json({message:o})}),hO(Dn);let t=parseInt(process.env.PORT||"5001",10);PI.listen({port:t,host:"0.0.0.0"},()=>{let e=`http://localhost:${t}`;console.log(`
1113
+ oh-my-pr v4.5.4
1114
1114
  Dashboard: ${e}
1115
1115
  `),!process.env.TAURI_DEV&&!process.env.OH_MY_PR_DESKTOP&&xae(e).catch(n=>{OI(`Could not open browser automatically: ${n.message}`)})})})();0&&(module.exports={log});
1116
1116
  /*! Bundled license information: