@botparty/nextjs 0.0.32 → 0.0.35

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/server.cjs CHANGED
@@ -1,7 +1,7 @@
1
- "use strict";var Pe=Object.create;var O=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var ve=Object.getPrototypeOf,_e=Object.prototype.hasOwnProperty;var Ee=(e,t)=>{for(var r in t)O(e,r,{get:t[r],enumerable:!0})},G=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Ae(t))!_e.call(e,s)&&s!==r&&O(e,s,{get:()=>t[s],enumerable:!(n=Ie(t,s))||n.enumerable});return e};var U=(e,t,r)=>(r=e!=null?Pe(ve(e)):{},G(t||!e||!e.__esModule?O(r,"default",{value:e,enumerable:!0}):r,e)),be=e=>G(O({},"__esModule",{value:!0}),e);var De={};Ee(De,{REFRESH_COOKIE:()=>E,SESSION_COOKIE:()=>_,auth:()=>C,botpartyMiddleware:()=>Re,configureJwksCache:()=>se,createJwksResponse:()=>fe,createPaymentGateway:()=>me,createRouteMatcher:()=>Se,createSession:()=>J,currentUser:()=>de,decodeToken:()=>Y,destroySession:()=>ee,drainJwksRevalidations:()=>oe,readSession:()=>b,verifyAccessToken:()=>q,verifyNamespaceToken:()=>$});module.exports=be(De);var le=require("next/headers"),P=require("next/navigation");var m=U(require("jose"),1),v=require("next/headers"),_="__botparty_session",E="__botparty_refresh",je="15m",Ce="30d",xe=900,Oe=720*60*60,V="https://id.botparty.club",N=null;async function L(){if(N)return N;let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)throw new Error("[BotParty] BOTPARTY_CLIENT_ASSERTION_KEY env var is not set");let t=`bp-session-key:${e}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return N=new Uint8Array(r),N}function X(e){return e.sub?{userId:e.sub,email:e.email,name:e.name,picture:e.picture,namespaceId:e.namespaceId,keyId:e.keyId,hasLinkedUser:e.hasLinkedUser??!1,accessToken:e.at,refreshToken:e.rt}:null}async function b(){let t=(await(0,v.cookies)()).get(_)?.value;if(!t)return null;try{let r=await L(),{payload:n}=await m.jwtDecrypt(t,r);return X(n)}catch{return null}}async function Q(){let t=(await(0,v.cookies)()).get(E)?.value;if(!t)return null;try{let r=await L(),{payload:n}=await m.jwtDecrypt(t,r);return X(n)}catch{return null}}function Z(e){return{email:e.email,name:e.name,picture:e.picture,namespaceId:e.namespaceId,keyId:e.keyId,hasLinkedUser:e.hasLinkedUser??!1,at:e.accessToken,rt:e.refreshToken}}async function Ue(e){let t=await L();return new m.EncryptJWT(Z(e)).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(e.userId).setIssuedAt().setExpirationTime(je).setIssuer(V).encrypt(t)}async function Ne(e){let t=await L();return new m.EncryptJWT(Z(e)).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(e.userId).setIssuedAt().setExpirationTime(Ce).setIssuer(V).encrypt(t)}async function J(e){let t=await(0,v.cookies)(),n={httpOnly:!0,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/"};t.set(_,await Ue(e),{...n,maxAge:xe}),t.set(E,await Ne(e),{...n,maxAge:Oe})}async function ee(){let e=await(0,v.cookies)();e.delete(_),e.delete(E)}var Le="urn:ietf:params:oauth:client-assertion-type:jwt-bearer";function te(e){try{let t=m.decodeJwt(e);return t.exp?t.exp<Math.floor(Date.now()/1e3)+60:!0}catch{return!0}}async function re(e){try{let t=process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club",r=process.env.BOTPARTY_CLIENT_ID,n=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r||!n)return null;let s=`${t}/oauth/token`,p=await m.importPKCS8(n.replace(/\\n/g,`
2
- `),"ES256"),c=await new m.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(r).setSubject(r).setAudience(s).setIssuedAt().setExpirationTime("60s").setJti(crypto.randomUUID()).sign(p),o=await fetch(s,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:r,client_assertion_type:Le,client_assertion:c})});if(!o.ok)return console.error("[BotParty] Token refresh failed:",o.status,await o.text().catch(()=>"")),null;let a=await o.json();return{accessToken:a.access_token,refreshToken:a.refresh_token}}catch(t){return console.error("[BotParty] Token refresh error:",t instanceof Error?t.message:t),null}}var w=U(require("jose"),1),H=600*1e3,B=new Map,k=null;function se(e){k=e}var K=[];async function oe(){let e=K;K=[],await Promise.allSettled(e.map(t=>t()))}async function ne(e){try{let t=await fetch(e,{cache:"no-store"});if(!t.ok)return;let r=await t.json();B.set(e,{jwks:r,expiresAt:Date.now()+H}),k&&await k.set(e,r)}catch{}}function F(){return process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club"}async function ae(e){let t=B.get(e);if(t&&Date.now()<t.expiresAt)return K.push(()=>ne(e)),t.jwks;if(k){let s=await k.get(e);if(s)return B.set(e,{jwks:s,expiresAt:Date.now()+H}),K.push(()=>ne(e)),s}let r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch JWKS from ${e}: ${r.status}`);let n=await r.json();return B.set(e,{jwks:n,expiresAt:Date.now()+H}),k&&await k.set(e,n),n}async function q(e){try{let t=`${F()}/.well-known/jwks.json`,r=await ae(t),n=w.createLocalJWKSet(r),{payload:s}=await w.jwtVerify(e,n,{algorithms:["ES256"],issuer:F()});return s}catch{return null}}async function $(e,t){try{let r=`${F()}/api/v1/namespaces/${encodeURIComponent(t)}/jwks.json`,n=await ae(r),s=w.createLocalJWKSet(n),{payload:p}=await w.jwtVerify(e,s);return p}catch{return null}}function Y(e){return w.decodeJwt(e)}var j="/api/botparty";function ie(e){return{isAuthenticated:!1,type:null,userId:null,namespaceId:null,keyId:null,email:null,name:null,picture:null,hasLinkedUser:!1,protect(){(0,P.redirect)(`${j}/auth/login`)},redirectToSignIn(t="/"){(0,P.redirect)(`${j}/auth/login?return_url=${encodeURIComponent(t)}`)},getToken(){return e}}}function ce(e,t){let r=e.namespaceId??(e.userId||null);return{isAuthenticated:!0,type:e.namespaceId?"bot":"human",userId:e.userId,namespaceId:r,keyId:e.keyId??null,email:e.email??null,name:e.name??null,picture:e.picture??null,hasLinkedUser:e.hasLinkedUser??!1,protect(){return this},redirectToSignIn(n="/"){(0,P.redirect)(`${j}/auth/login?return_url=${encodeURIComponent(n)}`)},getToken(){return t}}}async function C(){let t=(await(0,le.headers)()).get("authorization");if(t?.startsWith("Bearer ")){let s=t.slice(7),p=await q(s);if(p?.sub){let c={isAuthenticated:!0,type:"human",userId:p.sub,namespaceId:p.sub,keyId:null,email:p.email??null,name:p.name??null,picture:p.picture??null,hasLinkedUser:!0,protect(){return c},redirectToSignIn(o="/"){(0,P.redirect)(`${j}/auth/login?return_url=${encodeURIComponent(o)}`)},getToken(){return s}};return c}try{let c=Y(s),o=c.ns||c.iss;if(o){let a=await $(s,o);if(a){let u={isAuthenticated:!0,type:"bot",userId:a.sub??null,namespaceId:o,keyId:a.kid??null,email:null,name:null,picture:null,hasLinkedUser:a.linked??!1,protect(){return u},redirectToSignIn(l="/"){(0,P.redirect)(`${j}/auth/login?return_url=${encodeURIComponent(l)}`)},getToken(){return s}};return u}}}catch{}return ie(s)}let r=await b();if(r){let s=await ue(r);return ce(r,s)}let n=await Q();if(n){let s=await ue(n);return ce(n,s)}return ie(null)}async function ue(e){let t=e.accessToken??null;if(!t)return null;if(!te(t)||!e.refreshToken)return t;let r=await re(e.refreshToken);if(!r)return t;e.accessToken=r.accessToken,e.refreshToken=r.refreshToken;try{await J(e)}catch{}return r.accessToken}async function de(){return await b()}var T=U(require("jose"),1);function Je(e){let t=e.domain||process.env.BOTPARTY_DOMAIN||process.env.VERCEL_PROJECT_PRODUCTION_URL||"localhost:3000",r=e.privateKey||process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r)throw new Error("BotParty: missing private key. Pass privateKey in GatewayConfig or set BOTPARTY_CLIENT_ASSERTION_KEY.");return{domain:t,privateKey:r,serviceName:e.serviceName,serviceLogoUrl:e.serviceLogoUrl,facilitatorUrl:e.facilitatorUrl}}var z=null,pe=null;async function Be(e){return z&&pe===e||(z=await T.importPKCS8(e.replace(/\\n/g,`
3
- `),"ES256"),pe=e),z}async function Ke(e){let t=await Be(e.privateKey);return new T.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(e.domain).setIssuedAt().setExpirationTime("60s").sign(t)}function qe(e){return e.facilitatorUrl||process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club"}function ye(){return process.env.NEXT_PUBLIC_URL?process.env.NEXT_PUBLIC_URL.replace(/\/$/,""):process.env.VERCEL_URL?`https://${process.env.VERCEL_URL}`:"http://localhost:3000"}function $e(e,t,r,n,s){let p={x402Version:2,resource:{url:s,description:n},accepts:[{scheme:"redirect",network:"botparty:mainnet",asset:"botparty_credits",amount:String(r),payTo:t,maxTimeoutSeconds:300,extra:{description:n,serviceName:e.serviceName??e.domain,serviceLogoUrl:e.serviceLogoUrl}}]},c=Buffer.from(JSON.stringify(p)).toString("base64"),o={error:"payment_required",message:`Your human needs to validate this action by clicking this link:
4
- ${t}`,amount:String(r),asset:"botparty_credits",description:n??"",payTo:t,accepts:["redirect"]};return new Response(JSON.stringify(o),{status:402,headers:{"Content-Type":"application/json","PAYMENT-REQUIRED":c}})}function me(e={}){let t=Je(e),r=qe(e);async function n(c,o,a){try{let l={"Content-Type":"application/json","X-BotParty-Service":await Ke(t)};return o&&(l.Authorization=`Bearer ${o}`),await fetch(`${r}${c}`,{method:"POST",headers:l,body:JSON.stringify(a)})}catch(u){let l=u instanceof Error?u.message:String(u);throw console.error(`[BotParty] callFacilitator ${c} failed:`,l),new Error(`BotParty facilitator call failed: ${l}`)}}async function s(c,o,a,u){try{let l=await C(),i=l.getToken(),d=l.isAuthenticated&&!!i,h=u||c.url;if(d){let y=await n("/api/v1/payments/verify",i,{resource:h,amount:String(o)});if(y.ok){let A=await y.json();if(A.isValid)return{authorized:!0,response:new Response(null),payerNamespace:l.namespaceId??"",token:i,paymentRequestId:A.paymentRequestId??null,authorizationId:null}}}let R={resource:{url:h,description:a},amount:String(o),serviceName:t.serviceName,serviceLogoUrl:t.serviceLogoUrl};if(!d){let y=ye(),A=process.env.BOTPARTY_BASE_PATH||"/api/botparty";R.connectAppLoginUrl=`${y}${A}/auth/login?return_url=${encodeURIComponent(`${A}/auth/popup-done`)}`,R.connectAppDomain=t.domain}let S=await n("/api/v1/payments/create",d?i:null,R);if(!S.ok){let y=await S.text().catch(()=>"Facilitator error");return{authorized:!1,response:new Response(JSON.stringify({error:"facilitator_error",message:y}),{status:502,headers:{"Content-Type":"application/json"}}),payerNamespace:d?l.namespaceId??"":"",token:i??"",paymentRequestId:null,authorizationId:null}}let x=await S.json(),g=x.payTo;return{authorized:!1,response:$e(t,g,o,a,h),payerNamespace:d?l.namespaceId??"":"",token:i??"",paymentRequestId:x.extra?.paymentRequestId??null,authorizationId:null}}catch(l){let i=l instanceof Error?l.message:String(l);return console.error("[BotParty] doRequire() failed:",i),{authorized:!1,response:new Response(JSON.stringify({error:"gateway_error",message:i}),{status:500,headers:{"Content-Type":"application/json"}}),payerNamespace:"",token:"",paymentRequestId:null,authorizationId:null}}}async function p(c,o){try{let a=await C(),u=a.getToken(),l=a.isAuthenticated&&!!u;if(l){let g=await n("/api/v1/payments/verify",u,{providerId:o.provider.id});if(g.ok){let y=await g.json();if(y.isValid)return{authorized:!0,response:new Response(null),payerNamespace:a.namespaceId??"",token:u,paymentRequestId:null,authorizationId:y.authorizationId??null}}}let i={provider:o.provider,services:o.services,serviceName:t.serviceName,serviceLogoUrl:t.serviceLogoUrl};if(!l){let g=ye(),y=process.env.BOTPARTY_BASE_PATH||"/api/botparty";i.connectAppLoginUrl=`${g}${y}/auth/login?return_url=${encodeURIComponent(`${y}/auth/popup-done`)}`,i.connectAppDomain=t.domain}let d=await n("/api/v1/payments/create",l?u:null,i);if(!d.ok){let g=await d.text().catch(()=>"Facilitator error");return{authorized:!1,response:new Response(JSON.stringify({error:"facilitator_error",message:g}),{status:502,headers:{"Content-Type":"application/json"}}),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:null}}let h=await d.json(),R=h.payTo,S=h.authorizationId??null,x={error:"payment_required",message:`Your human needs to authorize this provider by clicking this link:
5
- ${R}`,asset:"botparty_credits",description:`Provider: ${o.provider.title}`,payTo:R,authorizationId:S,provider:o.provider};return{authorized:!1,response:new Response(JSON.stringify(x),{status:402,headers:{"Content-Type":"application/json"}}),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:S}}catch(a){let u=a instanceof Error?a.message:String(a);return console.error("[BotParty] doRequireProviderAccess() failed:",u),{authorized:!1,response:new Response(JSON.stringify({error:"gateway_error",message:u}),{status:500,headers:{"Content-Type":"application/json"}}),payerNamespace:"",token:"",paymentRequestId:null,authorizationId:null}}}return{async requirePayment(c,o){return s(c,o.amount,o.description,o.resource)},async requireBudget(c,o){return s(c,o.estimated,o.description,o.resource)},async requireProviderAccess(c,o){return p(c,o)},async claim(c,o){try{let a={amount:String(o.amount),description:o.description};c.authorizationId?a.authorizationId=c.authorizationId:c.paymentRequestId&&(a.paymentRequestId=c.paymentRequestId);let u=await n("/api/v1/payments/settle",c.token,a);return u.ok?await u.json():{success:!1,error:(await u.json().catch(()=>({error:"settle_failed"}))).error??"settle_failed",canContinue:!1}}catch(a){let u=a instanceof Error?a.message:String(a);return console.error("[BotParty] claim() failed:",u),{success:!1,error:u,canContinue:!1}}}}}async function fe(){let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)return Response.json({error:"BOTPARTY_CLIENT_ASSERTION_KEY must be set"},{status:500});let t=await T.importPKCS8(e.replace(/\\n/g,`
6
- `),"ES256"),r=await T.exportJWK(t),{d:n,...s}=r;return s.use="sig",s.alg="ES256",Response.json({keys:[s]},{headers:{"Cache-Control":"public, max-age=3600"}})}var M=require("next/server"),f=U(require("jose"),1),ke="__botparty_session",Te="__botparty_refresh",Ye="https://id.botparty.club",ze="urn:ietf:params:oauth:client-assertion-type:jwt-bearer";function he(e){try{let t=f.decodeJwt(e);return t.exp?t.exp<Math.floor(Date.now()/1e3)+60:!0}catch{return!0}}async function ge(e){try{let t=process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club",r=process.env.BOTPARTY_CLIENT_ID,n=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r||!n)return null;let s=`${t}/oauth/token`,p=await f.importPKCS8(n.replace(/\\n/g,`
7
- `),"ES256"),c=await new f.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(r).setSubject(r).setAudience(s).setIssuedAt().setExpirationTime("60s").setJti(crypto.randomUUID()).sign(p),o=await fetch(s,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:r,client_assertion_type:ze,client_assertion:c})});if(!o.ok)return null;let a=await o.json();return{accessToken:a.access_token,refreshToken:a.refresh_token}}catch{return null}}var W=null;async function We(){if(W)return W;let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)throw new Error("[BotParty] BOTPARTY_CLIENT_ASSERTION_KEY env var is not set");let t=`bp-session-key:${e}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return W=new Uint8Array(r),W}function Re(e){return async function(r){let n={refreshedToken:null,refreshedRefreshCookie:null,sessionPayload:null},s=await We(),p=r.cookies.get(ke)?.value;if(p)try{let{payload:i}=await f.jwtDecrypt(p,s);if(n.sessionPayload=i,i.at&&he(i.at)&&i.rt){let d=await ge(i.rt);d&&(i.at=d.accessToken,i.rt=d.refreshToken,n.sessionPayload=i,n.refreshedToken=await D(s,i,"15m"),n.refreshedRefreshCookie=await D(s,i,"30d"))}}catch{}if(!n.sessionPayload){let i=r.cookies.get(Te)?.value;if(i)try{let{payload:d}=await f.jwtDecrypt(i,s);if(d.sub){if(d.at&&he(d.at)&&d.rt){let h=await ge(d.rt);h&&(d.at=h.accessToken,d.rt=h.refreshToken)}n.sessionPayload=d,n.refreshedToken=await D(s,d,"15m"),n.refreshedRefreshCookie=await D(s,d,"30d")}}catch{}}let c=`${r.nextUrl.origin}/api/botparty/auth/login?return_url=${encodeURIComponent(r.nextUrl.pathname)}`,o=n.sessionPayload?.namespaceId??null,a=o??(n.sessionPayload?.sub||null),u=n.sessionPayload?{isAuthenticated:!0,type:o?"bot":"human",userId:n.sessionPayload.sub??null,namespaceId:a,email:n.sessionPayload.email??null,protect(){return this},redirectToSignIn(){throw new I(c)}}:{isAuthenticated:!1,type:null,userId:null,namespaceId:null,email:null,protect(){throw new I(c)},redirectToSignIn(){throw new I(c)}};try{if(e){let i=await e(u,r);if(i instanceof Response)return we(M.NextResponse.next({headers:i.headers}),n,r)}}catch(i){if(i instanceof I)return M.NextResponse.redirect(i.url);throw i}let l=M.NextResponse.next();return we(l,n,r)}}async function D(e,t,r){return new f.EncryptJWT({email:t.email,name:t.name,picture:t.picture,namespaceId:t.namespaceId,keyId:t.keyId,hasLinkedUser:t.hasLinkedUser,at:t.at,rt:t.rt}).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(t.sub).setIssuedAt().setExpirationTime(r).setIssuer(Ye).encrypt(e)}function we(e,t,r){let n={httpOnly:!0,secure:r.nextUrl.protocol==="https:",sameSite:"lax",path:"/"};return t.refreshedToken&&e.cookies.set(ke,t.refreshedToken,{...n,maxAge:900}),t.refreshedRefreshCookie&&e.cookies.set(Te,t.refreshedRefreshCookie,{...n,maxAge:720*60*60}),e}var I=class{url;constructor(t){this.url=t}};function Se(e){let t=e.map(r=>{if(r instanceof RegExp)return r;let s=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\.\\\*/,".*").replace(/\\\(/,"(").replace(/\\\)/,")");return new RegExp(`^${s}$`)});return r=>{let n=r.nextUrl.pathname;return t.some(s=>s.test(n))}}0&&(module.exports={REFRESH_COOKIE,SESSION_COOKIE,auth,botpartyMiddleware,configureJwksCache,createJwksResponse,createPaymentGateway,createRouteMatcher,createSession,currentUser,decodeToken,destroySession,drainJwksRevalidations,readSession,verifyAccessToken,verifyNamespaceToken});
1
+ "use strict";var Se=Object.create;var O=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var ve=Object.getOwnPropertyNames;var Ae=Object.getPrototypeOf,_e=Object.prototype.hasOwnProperty;var Ee=(e,t)=>{for(var r in t)O(e,r,{get:t[r],enumerable:!0})},G=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ve(t))!_e.call(e,s)&&s!==r&&O(e,s,{get:()=>t[s],enumerable:!(n=Ie(t,s))||n.enumerable});return e};var U=(e,t,r)=>(r=e!=null?Se(Ae(e)):{},G(t||!e||!e.__esModule?O(r,"default",{value:e,enumerable:!0}):r,e)),be=e=>G(O({},"__esModule",{value:!0}),e);var De={};Ee(De,{REFRESH_COOKIE:()=>b,SESSION_COOKIE:()=>E,auth:()=>x,botpartyMiddleware:()=>Re,configureJwksCache:()=>se,createJwksResponse:()=>fe,createPaymentGateway:()=>me,createRouteMatcher:()=>Pe,createSession:()=>J,currentUser:()=>de,decodeToken:()=>Y,destroySession:()=>ee,drainJwksRevalidations:()=>oe,readSession:()=>j,verifyAccessToken:()=>K,verifyNamespaceToken:()=>$});module.exports=be(De);var le=require("next/headers"),I=require("next/navigation");var m=U(require("jose"),1),_=require("next/headers"),E="__botparty_session",b="__botparty_refresh",je="15m",Ce="30d",xe=900,Oe=720*60*60,V="https://id.botparty.club",N=null;async function L(){if(N)return N;let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)throw new Error("[BotParty] BOTPARTY_CLIENT_ASSERTION_KEY env var is not set");let t=`bp-session-key:${e}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return N=new Uint8Array(r),N}function X(e){return e.sub?{userId:e.sub,email:e.email,name:e.name,picture:e.picture,namespaceId:e.namespaceId,keyId:e.keyId,hasLinkedUser:e.hasLinkedUser??!1,accessToken:e.at,refreshToken:e.rt}:null}async function j(){let t=(await(0,_.cookies)()).get(E)?.value;if(!t)return null;try{let r=await L(),{payload:n}=await m.jwtDecrypt(t,r);return X(n)}catch{return null}}async function Q(){let t=(await(0,_.cookies)()).get(b)?.value;if(!t)return null;try{let r=await L(),{payload:n}=await m.jwtDecrypt(t,r);return X(n)}catch{return null}}function Z(e){return{email:e.email,name:e.name,picture:e.picture,namespaceId:e.namespaceId,keyId:e.keyId,hasLinkedUser:e.hasLinkedUser??!1,at:e.accessToken,rt:e.refreshToken}}async function Ue(e){let t=await L();return new m.EncryptJWT(Z(e)).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(e.userId).setIssuedAt().setExpirationTime(je).setIssuer(V).encrypt(t)}async function Ne(e){let t=await L();return new m.EncryptJWT(Z(e)).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(e.userId).setIssuedAt().setExpirationTime(Ce).setIssuer(V).encrypt(t)}async function J(e){let t=await(0,_.cookies)(),n={httpOnly:!0,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/"};t.set(E,await Ue(e),{...n,maxAge:xe}),t.set(b,await Ne(e),{...n,maxAge:Oe})}async function ee(){let e=await(0,_.cookies)();e.delete(E),e.delete(b)}var Le="urn:ietf:params:oauth:client-assertion-type:jwt-bearer";function te(e){try{let t=m.decodeJwt(e);return t.exp?t.exp<Math.floor(Date.now()/1e3)+60:!0}catch{return!0}}async function re(e){try{let t=process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club",r=process.env.BOTPARTY_CLIENT_ID,n=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r||!n)return null;let s=`${t}/oauth/token`,p=await m.importPKCS8(n.replace(/\\n/g,`
2
+ `),"ES256"),c=await new m.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(r).setSubject(r).setAudience(s).setIssuedAt().setExpirationTime("60s").setJti(crypto.randomUUID()).sign(p),o=await fetch(s,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:r,client_assertion_type:Le,client_assertion:c})});if(!o.ok)return console.error("[BotParty] Token refresh failed:",o.status,await o.text().catch(()=>"")),null;let a=await o.json();return{accessToken:a.access_token,refreshToken:a.refresh_token}}catch(t){return console.error("[BotParty] Token refresh error:",t instanceof Error?t.message:t),null}}var w=U(require("jose"),1),H=600*1e3,B=new Map,P=null;function se(e){P=e}var q=[];async function oe(){let e=q;q=[],await Promise.allSettled(e.map(t=>t()))}async function ne(e){try{let t=await fetch(e,{cache:"no-store"});if(!t.ok)return;let r=await t.json();B.set(e,{jwks:r,expiresAt:Date.now()+H}),P&&await P.set(e,r)}catch{}}function F(){return process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club"}async function ae(e){let t=B.get(e);if(t&&Date.now()<t.expiresAt)return q.push(()=>ne(e)),t.jwks;if(P){let s=await P.get(e);if(s)return B.set(e,{jwks:s,expiresAt:Date.now()+H}),q.push(()=>ne(e)),s}let r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch JWKS from ${e}: ${r.status}`);let n=await r.json();return B.set(e,{jwks:n,expiresAt:Date.now()+H}),P&&await P.set(e,n),n}async function K(e){try{let t=`${F()}/.well-known/jwks.json`,r=await ae(t),n=w.createLocalJWKSet(r),{payload:s}=await w.jwtVerify(e,n,{algorithms:["ES256"],issuer:F()});return s}catch{return null}}async function $(e,t){try{let r=`${F()}/api/v1/namespaces/${encodeURIComponent(t)}/jwks.json`,n=await ae(r),s=w.createLocalJWKSet(n),{payload:p}=await w.jwtVerify(e,s);return p}catch{return null}}function Y(e){return w.decodeJwt(e)}var C="/api/botparty";function ie(e){return{isAuthenticated:!1,type:null,userId:null,namespaceId:null,keyId:null,email:null,name:null,picture:null,hasLinkedUser:!1,protect(){(0,I.redirect)(`${C}/auth/login`)},redirectToSignIn(t="/"){(0,I.redirect)(`${C}/auth/login?return_url=${encodeURIComponent(t)}`)},getToken(){return e}}}function ce(e,t){let r=e.namespaceId??(e.userId||null);return{isAuthenticated:!0,type:e.namespaceId?"bot":"human",userId:e.userId,namespaceId:r,keyId:e.keyId??null,email:e.email??null,name:e.name??null,picture:e.picture??null,hasLinkedUser:e.hasLinkedUser??!1,protect(){return this},redirectToSignIn(n="/"){(0,I.redirect)(`${C}/auth/login?return_url=${encodeURIComponent(n)}`)},getToken(){return t}}}async function x(){let t=(await(0,le.headers)()).get("authorization");if(t?.startsWith("Bearer ")){let s=t.slice(7),p=await K(s);if(p?.sub){let c={isAuthenticated:!0,type:"human",userId:p.sub,namespaceId:p.sub,keyId:null,email:p.email??null,name:p.name??null,picture:p.picture??null,hasLinkedUser:!0,protect(){return c},redirectToSignIn(o="/"){(0,I.redirect)(`${C}/auth/login?return_url=${encodeURIComponent(o)}`)},getToken(){return s}};return c}try{let c=Y(s),o=c.ns||c.iss;if(o){let a=await $(s,o);if(a){let u={isAuthenticated:!0,type:"bot",userId:a.sub??null,namespaceId:o,keyId:a.kid??null,email:null,name:null,picture:null,hasLinkedUser:a.linked??!1,protect(){return u},redirectToSignIn(l="/"){(0,I.redirect)(`${C}/auth/login?return_url=${encodeURIComponent(l)}`)},getToken(){return s}};return u}}}catch{}return ie(s)}let r=await j();if(r){let s=await ue(r);return ce(r,s)}let n=await Q();if(n){let s=await ue(n);return ce(n,s)}return ie(null)}async function ue(e){let t=e.accessToken??null;if(!t)return null;if(!te(t)||!e.refreshToken)return t;let r=await re(e.refreshToken);if(!r)return t;e.accessToken=r.accessToken,e.refreshToken=r.refreshToken;try{await J(e)}catch{}return r.accessToken}async function de(){return await j()}var S=U(require("jose"),1);function Je(e){let t=e.domain||process.env.BOTPARTY_DOMAIN||process.env.VERCEL_PROJECT_PRODUCTION_URL||"localhost:3000",r=e.privateKey||process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r)throw new Error("BotParty: missing private key. Pass privateKey in GatewayConfig or set BOTPARTY_CLIENT_ASSERTION_KEY.");return{domain:t,privateKey:r,serviceName:e.serviceName,serviceLogoUrl:e.serviceLogoUrl,facilitatorUrl:e.facilitatorUrl}}var z=null,pe=null;async function Be(e){return z&&pe===e||(z=await S.importPKCS8(e.replace(/\\n/g,`
3
+ `),"ES256"),pe=e),z}async function qe(e){let t=await Be(e.privateKey);return new S.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(e.domain).setIssuedAt().setExpirationTime("60s").sign(t)}function Ke(e){return e.facilitatorUrl||process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club"}function ye(){return process.env.NEXT_PUBLIC_URL?process.env.NEXT_PUBLIC_URL.replace(/\/$/,""):process.env.VERCEL_URL?`https://${process.env.VERCEL_URL}`:"http://localhost:3000"}function $e(e,t,r,n,s){let p={x402Version:2,resource:{url:s,description:n},accepts:[{scheme:"redirect",network:"botparty:mainnet",asset:"botparty_credits",amount:String(r),payTo:t,maxTimeoutSeconds:300,extra:{description:n,serviceName:e.serviceName??e.domain,serviceLogoUrl:e.serviceLogoUrl}}]},c=Buffer.from(JSON.stringify(p)).toString("base64"),o={error:"payment_required",message:`Your human needs to validate this action by clicking this link:
4
+ ${t}`,amount:String(r),asset:"botparty_credits",description:n??"",payTo:t,accepts:["redirect"]};return new Response(JSON.stringify(o),{status:402,headers:{"Content-Type":"application/json","PAYMENT-REQUIRED":c}})}function me(e={}){let t=Je(e),r=Ke(e);async function n(c,o,a){try{let l={"Content-Type":"application/json","X-BotParty-Service":await qe(t)};return o&&(l.Authorization=`Bearer ${o}`),await fetch(`${r}${c}`,{method:"POST",headers:l,body:JSON.stringify(a)})}catch(u){let l=u instanceof Error?u.message:String(u);throw console.error(`[BotParty] callFacilitator ${c} failed:`,l),new Error(`BotParty facilitator call failed: ${l}`)}}async function s(c,o,a,u){try{let l=await x(),i=l.getToken(),d=l.isAuthenticated&&!!i,f=u||c.url;if(d){let y=await n("/api/v1/payments/verify",i,{resource:f,amount:String(o)});if(y.ok){let A=await y.json();if(A.isValid)return{authorized:!0,response:new Response(null),payerNamespace:l.namespaceId??"",token:i,paymentRequestId:A.paymentRequestId??null,authorizationId:null}}}let k={resource:{url:f,description:a},amount:String(o),serviceName:t.serviceName,serviceLogoUrl:t.serviceLogoUrl};if(!d){let y=ye(),A=process.env.BOTPARTY_BASE_PATH||"/api/botparty";k.connectAppLoginUrl=`${y}${A}/auth/login?return_url=${encodeURIComponent(`${A}/auth/popup-done`)}`,k.connectAppDomain=t.domain}let T=await n("/api/v1/payments/create",d?i:null,k);if(!T.ok){let y=await T.text().catch(()=>"Facilitator error");return{authorized:!1,response:new Response(JSON.stringify({error:"facilitator_error",message:y}),{status:502,headers:{"Content-Type":"application/json"}}),payerNamespace:d?l.namespaceId??"":"",token:i??"",paymentRequestId:null,authorizationId:null}}let R=await T.json(),g=R.payTo;return{authorized:!1,response:$e(t,g,o,a,f),payerNamespace:d?l.namespaceId??"":"",token:i??"",paymentRequestId:R.extra?.paymentRequestId??null,authorizationId:null}}catch(l){let i=l instanceof Error?l.message:String(l);return console.error("[BotParty] doRequire() failed:",i),{authorized:!1,response:new Response(JSON.stringify({error:"gateway_error",message:i}),{status:500,headers:{"Content-Type":"application/json"}}),payerNamespace:"",token:"",paymentRequestId:null,authorizationId:null}}}async function p(c,o){try{let a=await x(),u=a.getToken(),l=a.isAuthenticated&&!!u;if(l){let g=await n("/api/v1/payments/verify",u,{providerId:o.provider.id});if(g.ok){let y=await g.json();if(y.isValid)return{authorized:!0,response:new Response(null),payerNamespace:a.namespaceId??"",token:u,paymentRequestId:null,authorizationId:y.authorizationId??null}}}let i={provider:o.provider,services:o.services,serviceName:t.serviceName,serviceLogoUrl:t.serviceLogoUrl};if(!l){let g=ye(),y=process.env.BOTPARTY_BASE_PATH||"/api/botparty";i.connectAppLoginUrl=`${g}${y}/auth/login?return_url=${encodeURIComponent(`${y}/auth/popup-done`)}`,i.connectAppDomain=t.domain}let d=await n("/api/v1/payments/create",l?u:null,i);if(!d.ok){let g=await d.text().catch(()=>"Facilitator error");return{authorized:!1,response:new Response(JSON.stringify({error:"facilitator_error",message:g}),{status:502,headers:{"Content-Type":"application/json"}}),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:null}}let f=await d.json(),k=f.payTo,T=f.authorizationId??null;if(d.status===200&&f.status==="active")return{authorized:!0,response:new Response(null),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:T};let R={error:"payment_required",asset:"botparty_credits",description:`Provider: ${o.provider.title}`,authorizationId:T,provider:o.provider};return k?(R.message=`Your human needs to authorize this provider by clicking this link:
5
+ ${k}`,R.payTo=k):R.message=`Payment authorization is required for ${o.provider.title}.`,{authorized:!1,response:new Response(JSON.stringify(R),{status:402,headers:{"Content-Type":"application/json"}}),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:T}}catch(a){let u=a instanceof Error?a.message:String(a);return console.error("[BotParty] doRequireProviderAccess() failed:",u),{authorized:!1,response:new Response(JSON.stringify({error:"gateway_error",message:u}),{status:500,headers:{"Content-Type":"application/json"}}),payerNamespace:"",token:"",paymentRequestId:null,authorizationId:null}}}return{async requirePayment(c,o){return s(c,o.amount,o.description,o.resource)},async requireBudget(c,o){return s(c,o.estimated,o.description,o.resource)},async requireProviderAccess(c,o){return p(c,o)},async claim(c,o){try{let a={amount:String(o.amount),description:o.description};c.authorizationId?a.authorizationId=c.authorizationId:c.paymentRequestId&&(a.paymentRequestId=c.paymentRequestId);let u=await n("/api/v1/payments/settle",c.token,a);return u.ok?await u.json():{success:!1,error:(await u.json().catch(()=>({error:"settle_failed"}))).error??"settle_failed",canContinue:!1}}catch(a){let u=a instanceof Error?a.message:String(a);return console.error("[BotParty] claim() failed:",u),{success:!1,error:u,canContinue:!1}}}}}async function fe(){let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)return Response.json({error:"BOTPARTY_CLIENT_ASSERTION_KEY must be set"},{status:500});let t=await S.importPKCS8(e.replace(/\\n/g,`
6
+ `),"ES256"),r=await S.exportJWK(t),{d:n,...s}=r;return s.use="sig",s.alg="ES256",Response.json({keys:[s]},{headers:{"Cache-Control":"public, max-age=3600"}})}var M=require("next/server"),h=U(require("jose"),1),ke="__botparty_session",Te="__botparty_refresh",Ye="https://id.botparty.club",ze="urn:ietf:params:oauth:client-assertion-type:jwt-bearer";function he(e){try{let t=h.decodeJwt(e);return t.exp?t.exp<Math.floor(Date.now()/1e3)+60:!0}catch{return!0}}async function ge(e){try{let t=process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club",r=process.env.BOTPARTY_CLIENT_ID,n=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r||!n)return null;let s=`${t}/oauth/token`,p=await h.importPKCS8(n.replace(/\\n/g,`
7
+ `),"ES256"),c=await new h.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(r).setSubject(r).setAudience(s).setIssuedAt().setExpirationTime("60s").setJti(crypto.randomUUID()).sign(p),o=await fetch(s,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:r,client_assertion_type:ze,client_assertion:c})});if(!o.ok)return null;let a=await o.json();return{accessToken:a.access_token,refreshToken:a.refresh_token}}catch{return null}}var W=null;async function We(){if(W)return W;let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)throw new Error("[BotParty] BOTPARTY_CLIENT_ASSERTION_KEY env var is not set");let t=`bp-session-key:${e}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return W=new Uint8Array(r),W}function Re(e){return async function(r){let n={refreshedToken:null,refreshedRefreshCookie:null,sessionPayload:null},s=await We(),p=r.cookies.get(ke)?.value;if(p)try{let{payload:i}=await h.jwtDecrypt(p,s);if(n.sessionPayload=i,i.at&&he(i.at)&&i.rt){let d=await ge(i.rt);d&&(i.at=d.accessToken,i.rt=d.refreshToken,n.sessionPayload=i,n.refreshedToken=await D(s,i,"15m"),n.refreshedRefreshCookie=await D(s,i,"30d"))}}catch{}if(!n.sessionPayload){let i=r.cookies.get(Te)?.value;if(i)try{let{payload:d}=await h.jwtDecrypt(i,s);if(d.sub){if(d.at&&he(d.at)&&d.rt){let f=await ge(d.rt);f&&(d.at=f.accessToken,d.rt=f.refreshToken)}n.sessionPayload=d,n.refreshedToken=await D(s,d,"15m"),n.refreshedRefreshCookie=await D(s,d,"30d")}}catch{}}let c=`${r.nextUrl.origin}/api/botparty/auth/login?return_url=${encodeURIComponent(r.nextUrl.pathname)}`,o=n.sessionPayload?.namespaceId??null,a=o??(n.sessionPayload?.sub||null),u=n.sessionPayload?{isAuthenticated:!0,type:o?"bot":"human",userId:n.sessionPayload.sub??null,namespaceId:a,email:n.sessionPayload.email??null,protect(){return this},redirectToSignIn(){throw new v(c)}}:{isAuthenticated:!1,type:null,userId:null,namespaceId:null,email:null,protect(){throw new v(c)},redirectToSignIn(){throw new v(c)}};try{if(e){let i=await e(u,r);if(i instanceof Response)return we(M.NextResponse.next({headers:i.headers}),n,r)}}catch(i){if(i instanceof v)return M.NextResponse.redirect(i.url);throw i}let l=M.NextResponse.next();return we(l,n,r)}}async function D(e,t,r){return new h.EncryptJWT({email:t.email,name:t.name,picture:t.picture,namespaceId:t.namespaceId,keyId:t.keyId,hasLinkedUser:t.hasLinkedUser,at:t.at,rt:t.rt}).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(t.sub).setIssuedAt().setExpirationTime(r).setIssuer(Ye).encrypt(e)}function we(e,t,r){let n={httpOnly:!0,secure:r.nextUrl.protocol==="https:",sameSite:"lax",path:"/"};return t.refreshedToken&&e.cookies.set(ke,t.refreshedToken,{...n,maxAge:900}),t.refreshedRefreshCookie&&e.cookies.set(Te,t.refreshedRefreshCookie,{...n,maxAge:720*60*60}),e}var v=class{url;constructor(t){this.url=t}};function Pe(e){let t=e.map(r=>{if(r instanceof RegExp)return r;let s=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\.\\\*/,".*").replace(/\\\(/,"(").replace(/\\\)/,")");return new RegExp(`^${s}$`)});return r=>{let n=r.nextUrl.pathname;return t.some(s=>s.test(n))}}0&&(module.exports={REFRESH_COOKIE,SESSION_COOKIE,auth,botpartyMiddleware,configureJwksCache,createJwksResponse,createPaymentGateway,createRouteMatcher,createSession,currentUser,decodeToken,destroySession,drainJwksRevalidations,readSession,verifyAccessToken,verifyNamespaceToken});
package/dist/server.js CHANGED
@@ -1,7 +1,7 @@
1
- import{headers as Re}from"next/headers";import{redirect as A}from"next/navigation";import*as m from"jose";import{cookies as b}from"next/headers";var j="__botparty_session",C="__botparty_refresh",de="15m",pe="30d",ye=900,me=720*60*60,H="https://id.botparty.club",E=null;async function x(){if(E)return E;let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)throw new Error("[BotParty] BOTPARTY_CLIENT_ASSERTION_KEY env var is not set");let t=`bp-session-key:${e}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return E=new Uint8Array(r),E}function F(e){return e.sub?{userId:e.sub,email:e.email,name:e.name,picture:e.picture,namespaceId:e.namespaceId,keyId:e.keyId,hasLinkedUser:e.hasLinkedUser??!1,accessToken:e.at,refreshToken:e.rt}:null}async function O(){let t=(await b()).get(j)?.value;if(!t)return null;try{let r=await x(),{payload:n}=await m.jwtDecrypt(t,r);return F(n)}catch{return null}}async function G(){let t=(await b()).get(C)?.value;if(!t)return null;try{let r=await x(),{payload:n}=await m.jwtDecrypt(t,r);return F(n)}catch{return null}}function V(e){return{email:e.email,name:e.name,picture:e.picture,namespaceId:e.namespaceId,keyId:e.keyId,hasLinkedUser:e.hasLinkedUser??!1,at:e.accessToken,rt:e.refreshToken}}async function fe(e){let t=await x();return new m.EncryptJWT(V(e)).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(e.userId).setIssuedAt().setExpirationTime(de).setIssuer(H).encrypt(t)}async function he(e){let t=await x();return new m.EncryptJWT(V(e)).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(e.userId).setIssuedAt().setExpirationTime(pe).setIssuer(H).encrypt(t)}async function q(e){let t=await b(),n={httpOnly:!0,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/"};t.set(j,await fe(e),{...n,maxAge:ye}),t.set(C,await he(e),{...n,maxAge:me})}async function ge(){let e=await b();e.delete(j),e.delete(C)}var we="urn:ietf:params:oauth:client-assertion-type:jwt-bearer";function X(e){try{let t=m.decodeJwt(e);return t.exp?t.exp<Math.floor(Date.now()/1e3)+60:!0}catch{return!0}}async function Q(e){try{let t=process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club",r=process.env.BOTPARTY_CLIENT_ID,n=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r||!n)return null;let s=`${t}/oauth/token`,p=await m.importPKCS8(n.replace(/\\n/g,`
2
- `),"ES256"),c=await new m.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(r).setSubject(r).setAudience(s).setIssuedAt().setExpirationTime("60s").setJti(crypto.randomUUID()).sign(p),o=await fetch(s,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:r,client_assertion_type:we,client_assertion:c})});if(!o.ok)return console.error("[BotParty] Token refresh failed:",o.status,await o.text().catch(()=>"")),null;let a=await o.json();return{accessToken:a.access_token,refreshToken:a.refresh_token}}catch(t){return console.error("[BotParty] Token refresh error:",t instanceof Error?t.message:t),null}}import*as w from"jose";var $=600*1e3,U=new Map,k=null;function ke(e){k=e}var N=[];async function Te(){let e=N;N=[],await Promise.allSettled(e.map(t=>t()))}async function Z(e){try{let t=await fetch(e,{cache:"no-store"});if(!t.ok)return;let r=await t.json();U.set(e,{jwks:r,expiresAt:Date.now()+$}),k&&await k.set(e,r)}catch{}}function Y(){return process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club"}async function ee(e){let t=U.get(e);if(t&&Date.now()<t.expiresAt)return N.push(()=>Z(e)),t.jwks;if(k){let s=await k.get(e);if(s)return U.set(e,{jwks:s,expiresAt:Date.now()+$}),N.push(()=>Z(e)),s}let r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch JWKS from ${e}: ${r.status}`);let n=await r.json();return U.set(e,{jwks:n,expiresAt:Date.now()+$}),k&&await k.set(e,n),n}async function z(e){try{let t=`${Y()}/.well-known/jwks.json`,r=await ee(t),n=w.createLocalJWKSet(r),{payload:s}=await w.jwtVerify(e,n,{algorithms:["ES256"],issuer:Y()});return s}catch{return null}}async function W(e,t){try{let r=`${Y()}/api/v1/namespaces/${encodeURIComponent(t)}/jwks.json`,n=await ee(r),s=w.createLocalJWKSet(n),{payload:p}=await w.jwtVerify(e,s);return p}catch{return null}}function D(e){return w.decodeJwt(e)}var v="/api/botparty";function te(e){return{isAuthenticated:!1,type:null,userId:null,namespaceId:null,keyId:null,email:null,name:null,picture:null,hasLinkedUser:!1,protect(){A(`${v}/auth/login`)},redirectToSignIn(t="/"){A(`${v}/auth/login?return_url=${encodeURIComponent(t)}`)},getToken(){return e}}}function re(e,t){let r=e.namespaceId??(e.userId||null);return{isAuthenticated:!0,type:e.namespaceId?"bot":"human",userId:e.userId,namespaceId:r,keyId:e.keyId??null,email:e.email??null,name:e.name??null,picture:e.picture??null,hasLinkedUser:e.hasLinkedUser??!1,protect(){return this},redirectToSignIn(n="/"){A(`${v}/auth/login?return_url=${encodeURIComponent(n)}`)},getToken(){return t}}}async function L(){let t=(await Re()).get("authorization");if(t?.startsWith("Bearer ")){let s=t.slice(7),p=await z(s);if(p?.sub){let c={isAuthenticated:!0,type:"human",userId:p.sub,namespaceId:p.sub,keyId:null,email:p.email??null,name:p.name??null,picture:p.picture??null,hasLinkedUser:!0,protect(){return c},redirectToSignIn(o="/"){A(`${v}/auth/login?return_url=${encodeURIComponent(o)}`)},getToken(){return s}};return c}try{let c=D(s),o=c.ns||c.iss;if(o){let a=await W(s,o);if(a){let u={isAuthenticated:!0,type:"bot",userId:a.sub??null,namespaceId:o,keyId:a.kid??null,email:null,name:null,picture:null,hasLinkedUser:a.linked??!1,protect(){return u},redirectToSignIn(l="/"){A(`${v}/auth/login?return_url=${encodeURIComponent(l)}`)},getToken(){return s}};return u}}}catch{}return te(s)}let r=await O();if(r){let s=await ne(r);return re(r,s)}let n=await G();if(n){let s=await ne(n);return re(n,s)}return te(null)}async function ne(e){let t=e.accessToken??null;if(!t)return null;if(!X(t)||!e.refreshToken)return t;let r=await Q(e.refreshToken);if(!r)return t;e.accessToken=r.accessToken,e.refreshToken=r.refreshToken;try{await q(e)}catch{}return r.accessToken}async function Se(){return await O()}import*as T from"jose";function Pe(e){let t=e.domain||process.env.BOTPARTY_DOMAIN||process.env.VERCEL_PROJECT_PRODUCTION_URL||"localhost:3000",r=e.privateKey||process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r)throw new Error("BotParty: missing private key. Pass privateKey in GatewayConfig or set BOTPARTY_CLIENT_ASSERTION_KEY.");return{domain:t,privateKey:r,serviceName:e.serviceName,serviceLogoUrl:e.serviceLogoUrl,facilitatorUrl:e.facilitatorUrl}}var J=null,se=null;async function Ie(e){return J&&se===e||(J=await T.importPKCS8(e.replace(/\\n/g,`
3
- `),"ES256"),se=e),J}async function Ae(e){let t=await Ie(e.privateKey);return new T.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(e.domain).setIssuedAt().setExpirationTime("60s").sign(t)}function ve(e){return e.facilitatorUrl||process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club"}function oe(){return process.env.NEXT_PUBLIC_URL?process.env.NEXT_PUBLIC_URL.replace(/\/$/,""):process.env.VERCEL_URL?`https://${process.env.VERCEL_URL}`:"http://localhost:3000"}function _e(e,t,r,n,s){let p={x402Version:2,resource:{url:s,description:n},accepts:[{scheme:"redirect",network:"botparty:mainnet",asset:"botparty_credits",amount:String(r),payTo:t,maxTimeoutSeconds:300,extra:{description:n,serviceName:e.serviceName??e.domain,serviceLogoUrl:e.serviceLogoUrl}}]},c=Buffer.from(JSON.stringify(p)).toString("base64"),o={error:"payment_required",message:`Your human needs to validate this action by clicking this link:
4
- ${t}`,amount:String(r),asset:"botparty_credits",description:n??"",payTo:t,accepts:["redirect"]};return new Response(JSON.stringify(o),{status:402,headers:{"Content-Type":"application/json","PAYMENT-REQUIRED":c}})}function Ee(e={}){let t=Pe(e),r=ve(e);async function n(c,o,a){try{let l={"Content-Type":"application/json","X-BotParty-Service":await Ae(t)};return o&&(l.Authorization=`Bearer ${o}`),await fetch(`${r}${c}`,{method:"POST",headers:l,body:JSON.stringify(a)})}catch(u){let l=u instanceof Error?u.message:String(u);throw console.error(`[BotParty] callFacilitator ${c} failed:`,l),new Error(`BotParty facilitator call failed: ${l}`)}}async function s(c,o,a,u){try{let l=await L(),i=l.getToken(),d=l.isAuthenticated&&!!i,h=u||c.url;if(d){let y=await n("/api/v1/payments/verify",i,{resource:h,amount:String(o)});if(y.ok){let I=await y.json();if(I.isValid)return{authorized:!0,response:new Response(null),payerNamespace:l.namespaceId??"",token:i,paymentRequestId:I.paymentRequestId??null,authorizationId:null}}}let R={resource:{url:h,description:a},amount:String(o),serviceName:t.serviceName,serviceLogoUrl:t.serviceLogoUrl};if(!d){let y=oe(),I=process.env.BOTPARTY_BASE_PATH||"/api/botparty";R.connectAppLoginUrl=`${y}${I}/auth/login?return_url=${encodeURIComponent(`${I}/auth/popup-done`)}`,R.connectAppDomain=t.domain}let S=await n("/api/v1/payments/create",d?i:null,R);if(!S.ok){let y=await S.text().catch(()=>"Facilitator error");return{authorized:!1,response:new Response(JSON.stringify({error:"facilitator_error",message:y}),{status:502,headers:{"Content-Type":"application/json"}}),payerNamespace:d?l.namespaceId??"":"",token:i??"",paymentRequestId:null,authorizationId:null}}let _=await S.json(),g=_.payTo;return{authorized:!1,response:_e(t,g,o,a,h),payerNamespace:d?l.namespaceId??"":"",token:i??"",paymentRequestId:_.extra?.paymentRequestId??null,authorizationId:null}}catch(l){let i=l instanceof Error?l.message:String(l);return console.error("[BotParty] doRequire() failed:",i),{authorized:!1,response:new Response(JSON.stringify({error:"gateway_error",message:i}),{status:500,headers:{"Content-Type":"application/json"}}),payerNamespace:"",token:"",paymentRequestId:null,authorizationId:null}}}async function p(c,o){try{let a=await L(),u=a.getToken(),l=a.isAuthenticated&&!!u;if(l){let g=await n("/api/v1/payments/verify",u,{providerId:o.provider.id});if(g.ok){let y=await g.json();if(y.isValid)return{authorized:!0,response:new Response(null),payerNamespace:a.namespaceId??"",token:u,paymentRequestId:null,authorizationId:y.authorizationId??null}}}let i={provider:o.provider,services:o.services,serviceName:t.serviceName,serviceLogoUrl:t.serviceLogoUrl};if(!l){let g=oe(),y=process.env.BOTPARTY_BASE_PATH||"/api/botparty";i.connectAppLoginUrl=`${g}${y}/auth/login?return_url=${encodeURIComponent(`${y}/auth/popup-done`)}`,i.connectAppDomain=t.domain}let d=await n("/api/v1/payments/create",l?u:null,i);if(!d.ok){let g=await d.text().catch(()=>"Facilitator error");return{authorized:!1,response:new Response(JSON.stringify({error:"facilitator_error",message:g}),{status:502,headers:{"Content-Type":"application/json"}}),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:null}}let h=await d.json(),R=h.payTo,S=h.authorizationId??null,_={error:"payment_required",message:`Your human needs to authorize this provider by clicking this link:
5
- ${R}`,asset:"botparty_credits",description:`Provider: ${o.provider.title}`,payTo:R,authorizationId:S,provider:o.provider};return{authorized:!1,response:new Response(JSON.stringify(_),{status:402,headers:{"Content-Type":"application/json"}}),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:S}}catch(a){let u=a instanceof Error?a.message:String(a);return console.error("[BotParty] doRequireProviderAccess() failed:",u),{authorized:!1,response:new Response(JSON.stringify({error:"gateway_error",message:u}),{status:500,headers:{"Content-Type":"application/json"}}),payerNamespace:"",token:"",paymentRequestId:null,authorizationId:null}}}return{async requirePayment(c,o){return s(c,o.amount,o.description,o.resource)},async requireBudget(c,o){return s(c,o.estimated,o.description,o.resource)},async requireProviderAccess(c,o){return p(c,o)},async claim(c,o){try{let a={amount:String(o.amount),description:o.description};c.authorizationId?a.authorizationId=c.authorizationId:c.paymentRequestId&&(a.paymentRequestId=c.paymentRequestId);let u=await n("/api/v1/payments/settle",c.token,a);return u.ok?await u.json():{success:!1,error:(await u.json().catch(()=>({error:"settle_failed"}))).error??"settle_failed",canContinue:!1}}catch(a){let u=a instanceof Error?a.message:String(a);return console.error("[BotParty] claim() failed:",u),{success:!1,error:u,canContinue:!1}}}}}async function be(){let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)return Response.json({error:"BOTPARTY_CLIENT_ASSERTION_KEY must be set"},{status:500});let t=await T.importPKCS8(e.replace(/\\n/g,`
6
- `),"ES256"),r=await T.exportJWK(t),{d:n,...s}=r;return s.use="sig",s.alg="ES256",Response.json({keys:[s]},{headers:{"Cache-Control":"public, max-age=3600"}})}import{NextResponse as M}from"next/server";import*as f from"jose";var ue="__botparty_session",le="__botparty_refresh",je="https://id.botparty.club",Ce="urn:ietf:params:oauth:client-assertion-type:jwt-bearer";function ae(e){try{let t=f.decodeJwt(e);return t.exp?t.exp<Math.floor(Date.now()/1e3)+60:!0}catch{return!0}}async function ie(e){try{let t=process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club",r=process.env.BOTPARTY_CLIENT_ID,n=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r||!n)return null;let s=`${t}/oauth/token`,p=await f.importPKCS8(n.replace(/\\n/g,`
7
- `),"ES256"),c=await new f.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(r).setSubject(r).setAudience(s).setIssuedAt().setExpirationTime("60s").setJti(crypto.randomUUID()).sign(p),o=await fetch(s,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:r,client_assertion_type:Ce,client_assertion:c})});if(!o.ok)return null;let a=await o.json();return{accessToken:a.access_token,refreshToken:a.refresh_token}}catch{return null}}var B=null;async function xe(){if(B)return B;let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)throw new Error("[BotParty] BOTPARTY_CLIENT_ASSERTION_KEY env var is not set");let t=`bp-session-key:${e}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return B=new Uint8Array(r),B}function Oe(e){return async function(r){let n={refreshedToken:null,refreshedRefreshCookie:null,sessionPayload:null},s=await xe(),p=r.cookies.get(ue)?.value;if(p)try{let{payload:i}=await f.jwtDecrypt(p,s);if(n.sessionPayload=i,i.at&&ae(i.at)&&i.rt){let d=await ie(i.rt);d&&(i.at=d.accessToken,i.rt=d.refreshToken,n.sessionPayload=i,n.refreshedToken=await K(s,i,"15m"),n.refreshedRefreshCookie=await K(s,i,"30d"))}}catch{}if(!n.sessionPayload){let i=r.cookies.get(le)?.value;if(i)try{let{payload:d}=await f.jwtDecrypt(i,s);if(d.sub){if(d.at&&ae(d.at)&&d.rt){let h=await ie(d.rt);h&&(d.at=h.accessToken,d.rt=h.refreshToken)}n.sessionPayload=d,n.refreshedToken=await K(s,d,"15m"),n.refreshedRefreshCookie=await K(s,d,"30d")}}catch{}}let c=`${r.nextUrl.origin}/api/botparty/auth/login?return_url=${encodeURIComponent(r.nextUrl.pathname)}`,o=n.sessionPayload?.namespaceId??null,a=o??(n.sessionPayload?.sub||null),u=n.sessionPayload?{isAuthenticated:!0,type:o?"bot":"human",userId:n.sessionPayload.sub??null,namespaceId:a,email:n.sessionPayload.email??null,protect(){return this},redirectToSignIn(){throw new P(c)}}:{isAuthenticated:!1,type:null,userId:null,namespaceId:null,email:null,protect(){throw new P(c)},redirectToSignIn(){throw new P(c)}};try{if(e){let i=await e(u,r);if(i instanceof Response)return ce(M.next({headers:i.headers}),n,r)}}catch(i){if(i instanceof P)return M.redirect(i.url);throw i}let l=M.next();return ce(l,n,r)}}async function K(e,t,r){return new f.EncryptJWT({email:t.email,name:t.name,picture:t.picture,namespaceId:t.namespaceId,keyId:t.keyId,hasLinkedUser:t.hasLinkedUser,at:t.at,rt:t.rt}).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(t.sub).setIssuedAt().setExpirationTime(r).setIssuer(je).encrypt(e)}function ce(e,t,r){let n={httpOnly:!0,secure:r.nextUrl.protocol==="https:",sameSite:"lax",path:"/"};return t.refreshedToken&&e.cookies.set(ue,t.refreshedToken,{...n,maxAge:900}),t.refreshedRefreshCookie&&e.cookies.set(le,t.refreshedRefreshCookie,{...n,maxAge:720*60*60}),e}var P=class{url;constructor(t){this.url=t}};function Ue(e){let t=e.map(r=>{if(r instanceof RegExp)return r;let s=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\.\\\*/,".*").replace(/\\\(/,"(").replace(/\\\)/,")");return new RegExp(`^${s}$`)});return r=>{let n=r.nextUrl.pathname;return t.some(s=>s.test(n))}}export{C as REFRESH_COOKIE,j as SESSION_COOKIE,L as auth,Oe as botpartyMiddleware,ke as configureJwksCache,be as createJwksResponse,Ee as createPaymentGateway,Ue as createRouteMatcher,q as createSession,Se as currentUser,D as decodeToken,ge as destroySession,Te as drainJwksRevalidations,O as readSession,z as verifyAccessToken,W as verifyNamespaceToken};
1
+ import{headers as Re}from"next/headers";import{redirect as A}from"next/navigation";import*as m from"jose";import{cookies as b}from"next/headers";var j="__botparty_session",C="__botparty_refresh",de="15m",pe="30d",ye=900,me=720*60*60,H="https://id.botparty.club",E=null;async function x(){if(E)return E;let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)throw new Error("[BotParty] BOTPARTY_CLIENT_ASSERTION_KEY env var is not set");let t=`bp-session-key:${e}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return E=new Uint8Array(r),E}function F(e){return e.sub?{userId:e.sub,email:e.email,name:e.name,picture:e.picture,namespaceId:e.namespaceId,keyId:e.keyId,hasLinkedUser:e.hasLinkedUser??!1,accessToken:e.at,refreshToken:e.rt}:null}async function O(){let t=(await b()).get(j)?.value;if(!t)return null;try{let r=await x(),{payload:n}=await m.jwtDecrypt(t,r);return F(n)}catch{return null}}async function G(){let t=(await b()).get(C)?.value;if(!t)return null;try{let r=await x(),{payload:n}=await m.jwtDecrypt(t,r);return F(n)}catch{return null}}function V(e){return{email:e.email,name:e.name,picture:e.picture,namespaceId:e.namespaceId,keyId:e.keyId,hasLinkedUser:e.hasLinkedUser??!1,at:e.accessToken,rt:e.refreshToken}}async function fe(e){let t=await x();return new m.EncryptJWT(V(e)).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(e.userId).setIssuedAt().setExpirationTime(de).setIssuer(H).encrypt(t)}async function he(e){let t=await x();return new m.EncryptJWT(V(e)).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(e.userId).setIssuedAt().setExpirationTime(pe).setIssuer(H).encrypt(t)}async function K(e){let t=await b(),n={httpOnly:!0,secure:process.env.NODE_ENV==="production",sameSite:"lax",path:"/"};t.set(j,await fe(e),{...n,maxAge:ye}),t.set(C,await he(e),{...n,maxAge:me})}async function ge(){let e=await b();e.delete(j),e.delete(C)}var we="urn:ietf:params:oauth:client-assertion-type:jwt-bearer";function X(e){try{let t=m.decodeJwt(e);return t.exp?t.exp<Math.floor(Date.now()/1e3)+60:!0}catch{return!0}}async function Q(e){try{let t=process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club",r=process.env.BOTPARTY_CLIENT_ID,n=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r||!n)return null;let o=`${t}/oauth/token`,p=await m.importPKCS8(n.replace(/\\n/g,`
2
+ `),"ES256"),c=await new m.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(r).setSubject(r).setAudience(o).setIssuedAt().setExpirationTime("60s").setJti(crypto.randomUUID()).sign(p),s=await fetch(o,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:r,client_assertion_type:we,client_assertion:c})});if(!s.ok)return console.error("[BotParty] Token refresh failed:",s.status,await s.text().catch(()=>"")),null;let a=await s.json();return{accessToken:a.access_token,refreshToken:a.refresh_token}}catch(t){return console.error("[BotParty] Token refresh error:",t instanceof Error?t.message:t),null}}import*as w from"jose";var $=600*1e3,U=new Map,P=null;function ke(e){P=e}var N=[];async function Te(){let e=N;N=[],await Promise.allSettled(e.map(t=>t()))}async function Z(e){try{let t=await fetch(e,{cache:"no-store"});if(!t.ok)return;let r=await t.json();U.set(e,{jwks:r,expiresAt:Date.now()+$}),P&&await P.set(e,r)}catch{}}function Y(){return process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club"}async function ee(e){let t=U.get(e);if(t&&Date.now()<t.expiresAt)return N.push(()=>Z(e)),t.jwks;if(P){let o=await P.get(e);if(o)return U.set(e,{jwks:o,expiresAt:Date.now()+$}),N.push(()=>Z(e)),o}let r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch JWKS from ${e}: ${r.status}`);let n=await r.json();return U.set(e,{jwks:n,expiresAt:Date.now()+$}),P&&await P.set(e,n),n}async function z(e){try{let t=`${Y()}/.well-known/jwks.json`,r=await ee(t),n=w.createLocalJWKSet(r),{payload:o}=await w.jwtVerify(e,n,{algorithms:["ES256"],issuer:Y()});return o}catch{return null}}async function W(e,t){try{let r=`${Y()}/api/v1/namespaces/${encodeURIComponent(t)}/jwks.json`,n=await ee(r),o=w.createLocalJWKSet(n),{payload:p}=await w.jwtVerify(e,o);return p}catch{return null}}function D(e){return w.decodeJwt(e)}var _="/api/botparty";function te(e){return{isAuthenticated:!1,type:null,userId:null,namespaceId:null,keyId:null,email:null,name:null,picture:null,hasLinkedUser:!1,protect(){A(`${_}/auth/login`)},redirectToSignIn(t="/"){A(`${_}/auth/login?return_url=${encodeURIComponent(t)}`)},getToken(){return e}}}function re(e,t){let r=e.namespaceId??(e.userId||null);return{isAuthenticated:!0,type:e.namespaceId?"bot":"human",userId:e.userId,namespaceId:r,keyId:e.keyId??null,email:e.email??null,name:e.name??null,picture:e.picture??null,hasLinkedUser:e.hasLinkedUser??!1,protect(){return this},redirectToSignIn(n="/"){A(`${_}/auth/login?return_url=${encodeURIComponent(n)}`)},getToken(){return t}}}async function L(){let t=(await Re()).get("authorization");if(t?.startsWith("Bearer ")){let o=t.slice(7),p=await z(o);if(p?.sub){let c={isAuthenticated:!0,type:"human",userId:p.sub,namespaceId:p.sub,keyId:null,email:p.email??null,name:p.name??null,picture:p.picture??null,hasLinkedUser:!0,protect(){return c},redirectToSignIn(s="/"){A(`${_}/auth/login?return_url=${encodeURIComponent(s)}`)},getToken(){return o}};return c}try{let c=D(o),s=c.ns||c.iss;if(s){let a=await W(o,s);if(a){let u={isAuthenticated:!0,type:"bot",userId:a.sub??null,namespaceId:s,keyId:a.kid??null,email:null,name:null,picture:null,hasLinkedUser:a.linked??!1,protect(){return u},redirectToSignIn(l="/"){A(`${_}/auth/login?return_url=${encodeURIComponent(l)}`)},getToken(){return o}};return u}}}catch{}return te(o)}let r=await O();if(r){let o=await ne(r);return re(r,o)}let n=await G();if(n){let o=await ne(n);return re(n,o)}return te(null)}async function ne(e){let t=e.accessToken??null;if(!t)return null;if(!X(t)||!e.refreshToken)return t;let r=await Q(e.refreshToken);if(!r)return t;e.accessToken=r.accessToken,e.refreshToken=r.refreshToken;try{await K(e)}catch{}return r.accessToken}async function Pe(){return await O()}import*as S from"jose";function Se(e){let t=e.domain||process.env.BOTPARTY_DOMAIN||process.env.VERCEL_PROJECT_PRODUCTION_URL||"localhost:3000",r=e.privateKey||process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r)throw new Error("BotParty: missing private key. Pass privateKey in GatewayConfig or set BOTPARTY_CLIENT_ASSERTION_KEY.");return{domain:t,privateKey:r,serviceName:e.serviceName,serviceLogoUrl:e.serviceLogoUrl,facilitatorUrl:e.facilitatorUrl}}var J=null,se=null;async function Ie(e){return J&&se===e||(J=await S.importPKCS8(e.replace(/\\n/g,`
3
+ `),"ES256"),se=e),J}async function ve(e){let t=await Ie(e.privateKey);return new S.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(e.domain).setIssuedAt().setExpirationTime("60s").sign(t)}function Ae(e){return e.facilitatorUrl||process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club"}function oe(){return process.env.NEXT_PUBLIC_URL?process.env.NEXT_PUBLIC_URL.replace(/\/$/,""):process.env.VERCEL_URL?`https://${process.env.VERCEL_URL}`:"http://localhost:3000"}function _e(e,t,r,n,o){let p={x402Version:2,resource:{url:o,description:n},accepts:[{scheme:"redirect",network:"botparty:mainnet",asset:"botparty_credits",amount:String(r),payTo:t,maxTimeoutSeconds:300,extra:{description:n,serviceName:e.serviceName??e.domain,serviceLogoUrl:e.serviceLogoUrl}}]},c=Buffer.from(JSON.stringify(p)).toString("base64"),s={error:"payment_required",message:`Your human needs to validate this action by clicking this link:
4
+ ${t}`,amount:String(r),asset:"botparty_credits",description:n??"",payTo:t,accepts:["redirect"]};return new Response(JSON.stringify(s),{status:402,headers:{"Content-Type":"application/json","PAYMENT-REQUIRED":c}})}function Ee(e={}){let t=Se(e),r=Ae(e);async function n(c,s,a){try{let l={"Content-Type":"application/json","X-BotParty-Service":await ve(t)};return s&&(l.Authorization=`Bearer ${s}`),await fetch(`${r}${c}`,{method:"POST",headers:l,body:JSON.stringify(a)})}catch(u){let l=u instanceof Error?u.message:String(u);throw console.error(`[BotParty] callFacilitator ${c} failed:`,l),new Error(`BotParty facilitator call failed: ${l}`)}}async function o(c,s,a,u){try{let l=await L(),i=l.getToken(),d=l.isAuthenticated&&!!i,f=u||c.url;if(d){let y=await n("/api/v1/payments/verify",i,{resource:f,amount:String(s)});if(y.ok){let v=await y.json();if(v.isValid)return{authorized:!0,response:new Response(null),payerNamespace:l.namespaceId??"",token:i,paymentRequestId:v.paymentRequestId??null,authorizationId:null}}}let k={resource:{url:f,description:a},amount:String(s),serviceName:t.serviceName,serviceLogoUrl:t.serviceLogoUrl};if(!d){let y=oe(),v=process.env.BOTPARTY_BASE_PATH||"/api/botparty";k.connectAppLoginUrl=`${y}${v}/auth/login?return_url=${encodeURIComponent(`${v}/auth/popup-done`)}`,k.connectAppDomain=t.domain}let T=await n("/api/v1/payments/create",d?i:null,k);if(!T.ok){let y=await T.text().catch(()=>"Facilitator error");return{authorized:!1,response:new Response(JSON.stringify({error:"facilitator_error",message:y}),{status:502,headers:{"Content-Type":"application/json"}}),payerNamespace:d?l.namespaceId??"":"",token:i??"",paymentRequestId:null,authorizationId:null}}let R=await T.json(),g=R.payTo;return{authorized:!1,response:_e(t,g,s,a,f),payerNamespace:d?l.namespaceId??"":"",token:i??"",paymentRequestId:R.extra?.paymentRequestId??null,authorizationId:null}}catch(l){let i=l instanceof Error?l.message:String(l);return console.error("[BotParty] doRequire() failed:",i),{authorized:!1,response:new Response(JSON.stringify({error:"gateway_error",message:i}),{status:500,headers:{"Content-Type":"application/json"}}),payerNamespace:"",token:"",paymentRequestId:null,authorizationId:null}}}async function p(c,s){try{let a=await L(),u=a.getToken(),l=a.isAuthenticated&&!!u;if(l){let g=await n("/api/v1/payments/verify",u,{providerId:s.provider.id});if(g.ok){let y=await g.json();if(y.isValid)return{authorized:!0,response:new Response(null),payerNamespace:a.namespaceId??"",token:u,paymentRequestId:null,authorizationId:y.authorizationId??null}}}let i={provider:s.provider,services:s.services,serviceName:t.serviceName,serviceLogoUrl:t.serviceLogoUrl};if(!l){let g=oe(),y=process.env.BOTPARTY_BASE_PATH||"/api/botparty";i.connectAppLoginUrl=`${g}${y}/auth/login?return_url=${encodeURIComponent(`${y}/auth/popup-done`)}`,i.connectAppDomain=t.domain}let d=await n("/api/v1/payments/create",l?u:null,i);if(!d.ok){let g=await d.text().catch(()=>"Facilitator error");return{authorized:!1,response:new Response(JSON.stringify({error:"facilitator_error",message:g}),{status:502,headers:{"Content-Type":"application/json"}}),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:null}}let f=await d.json(),k=f.payTo,T=f.authorizationId??null;if(d.status===200&&f.status==="active")return{authorized:!0,response:new Response(null),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:T};let R={error:"payment_required",asset:"botparty_credits",description:`Provider: ${s.provider.title}`,authorizationId:T,provider:s.provider};return k?(R.message=`Your human needs to authorize this provider by clicking this link:
5
+ ${k}`,R.payTo=k):R.message=`Payment authorization is required for ${s.provider.title}.`,{authorized:!1,response:new Response(JSON.stringify(R),{status:402,headers:{"Content-Type":"application/json"}}),payerNamespace:l?a.namespaceId??"":"",token:u??"",paymentRequestId:null,authorizationId:T}}catch(a){let u=a instanceof Error?a.message:String(a);return console.error("[BotParty] doRequireProviderAccess() failed:",u),{authorized:!1,response:new Response(JSON.stringify({error:"gateway_error",message:u}),{status:500,headers:{"Content-Type":"application/json"}}),payerNamespace:"",token:"",paymentRequestId:null,authorizationId:null}}}return{async requirePayment(c,s){return o(c,s.amount,s.description,s.resource)},async requireBudget(c,s){return o(c,s.estimated,s.description,s.resource)},async requireProviderAccess(c,s){return p(c,s)},async claim(c,s){try{let a={amount:String(s.amount),description:s.description};c.authorizationId?a.authorizationId=c.authorizationId:c.paymentRequestId&&(a.paymentRequestId=c.paymentRequestId);let u=await n("/api/v1/payments/settle",c.token,a);return u.ok?await u.json():{success:!1,error:(await u.json().catch(()=>({error:"settle_failed"}))).error??"settle_failed",canContinue:!1}}catch(a){let u=a instanceof Error?a.message:String(a);return console.error("[BotParty] claim() failed:",u),{success:!1,error:u,canContinue:!1}}}}}async function be(){let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)return Response.json({error:"BOTPARTY_CLIENT_ASSERTION_KEY must be set"},{status:500});let t=await S.importPKCS8(e.replace(/\\n/g,`
6
+ `),"ES256"),r=await S.exportJWK(t),{d:n,...o}=r;return o.use="sig",o.alg="ES256",Response.json({keys:[o]},{headers:{"Cache-Control":"public, max-age=3600"}})}import{NextResponse as M}from"next/server";import*as h from"jose";var ue="__botparty_session",le="__botparty_refresh",je="https://id.botparty.club",Ce="urn:ietf:params:oauth:client-assertion-type:jwt-bearer";function ae(e){try{let t=h.decodeJwt(e);return t.exp?t.exp<Math.floor(Date.now()/1e3)+60:!0}catch{return!0}}async function ie(e){try{let t=process.env.BOTPARTY_AUTH_URL||"https://id.botparty.club",r=process.env.BOTPARTY_CLIENT_ID,n=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!r||!n)return null;let o=`${t}/oauth/token`,p=await h.importPKCS8(n.replace(/\\n/g,`
7
+ `),"ES256"),c=await new h.SignJWT({}).setProtectedHeader({alg:"ES256"}).setIssuer(r).setSubject(r).setAudience(o).setIssuedAt().setExpirationTime("60s").setJti(crypto.randomUUID()).sign(p),s=await fetch(o,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:r,client_assertion_type:Ce,client_assertion:c})});if(!s.ok)return null;let a=await s.json();return{accessToken:a.access_token,refreshToken:a.refresh_token}}catch{return null}}var B=null;async function xe(){if(B)return B;let e=process.env.BOTPARTY_CLIENT_ASSERTION_KEY;if(!e)throw new Error("[BotParty] BOTPARTY_CLIENT_ASSERTION_KEY env var is not set");let t=`bp-session-key:${e}`,r=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return B=new Uint8Array(r),B}function Oe(e){return async function(r){let n={refreshedToken:null,refreshedRefreshCookie:null,sessionPayload:null},o=await xe(),p=r.cookies.get(ue)?.value;if(p)try{let{payload:i}=await h.jwtDecrypt(p,o);if(n.sessionPayload=i,i.at&&ae(i.at)&&i.rt){let d=await ie(i.rt);d&&(i.at=d.accessToken,i.rt=d.refreshToken,n.sessionPayload=i,n.refreshedToken=await q(o,i,"15m"),n.refreshedRefreshCookie=await q(o,i,"30d"))}}catch{}if(!n.sessionPayload){let i=r.cookies.get(le)?.value;if(i)try{let{payload:d}=await h.jwtDecrypt(i,o);if(d.sub){if(d.at&&ae(d.at)&&d.rt){let f=await ie(d.rt);f&&(d.at=f.accessToken,d.rt=f.refreshToken)}n.sessionPayload=d,n.refreshedToken=await q(o,d,"15m"),n.refreshedRefreshCookie=await q(o,d,"30d")}}catch{}}let c=`${r.nextUrl.origin}/api/botparty/auth/login?return_url=${encodeURIComponent(r.nextUrl.pathname)}`,s=n.sessionPayload?.namespaceId??null,a=s??(n.sessionPayload?.sub||null),u=n.sessionPayload?{isAuthenticated:!0,type:s?"bot":"human",userId:n.sessionPayload.sub??null,namespaceId:a,email:n.sessionPayload.email??null,protect(){return this},redirectToSignIn(){throw new I(c)}}:{isAuthenticated:!1,type:null,userId:null,namespaceId:null,email:null,protect(){throw new I(c)},redirectToSignIn(){throw new I(c)}};try{if(e){let i=await e(u,r);if(i instanceof Response)return ce(M.next({headers:i.headers}),n,r)}}catch(i){if(i instanceof I)return M.redirect(i.url);throw i}let l=M.next();return ce(l,n,r)}}async function q(e,t,r){return new h.EncryptJWT({email:t.email,name:t.name,picture:t.picture,namespaceId:t.namespaceId,keyId:t.keyId,hasLinkedUser:t.hasLinkedUser,at:t.at,rt:t.rt}).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setSubject(t.sub).setIssuedAt().setExpirationTime(r).setIssuer(je).encrypt(e)}function ce(e,t,r){let n={httpOnly:!0,secure:r.nextUrl.protocol==="https:",sameSite:"lax",path:"/"};return t.refreshedToken&&e.cookies.set(ue,t.refreshedToken,{...n,maxAge:900}),t.refreshedRefreshCookie&&e.cookies.set(le,t.refreshedRefreshCookie,{...n,maxAge:720*60*60}),e}var I=class{url;constructor(t){this.url=t}};function Ue(e){let t=e.map(r=>{if(r instanceof RegExp)return r;let o=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\.\\\*/,".*").replace(/\\\(/,"(").replace(/\\\)/,")");return new RegExp(`^${o}$`)});return r=>{let n=r.nextUrl.pathname;return t.some(o=>o.test(n))}}export{C as REFRESH_COOKIE,j as SESSION_COOKIE,L as auth,Oe as botpartyMiddleware,ke as configureJwksCache,be as createJwksResponse,Ee as createPaymentGateway,Ue as createRouteMatcher,K as createSession,Pe as currentUser,D as decodeToken,ge as destroySession,Te as drainJwksRevalidations,O as readSession,z as verifyAccessToken,W as verifyNamespaceToken};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botparty/nextjs",
3
- "version": "0.0.32",
3
+ "version": "0.0.35",
4
4
  "description": "Next.js SDK for BotParty auth — middleware, server auth(), route handlers, SSR provider",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -63,7 +63,7 @@
63
63
  "dev": "tsc --watch"
64
64
  },
65
65
  "dependencies": {
66
- "@botparty/react": "0.0.32",
66
+ "@botparty/react": "0.0.35",
67
67
  "jose": "^6.1.2"
68
68
  },
69
69
  "peerDependencies": {