@drip-sdk/node 1.0.10 → 1.1.0

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.
@@ -1,6 +1,6 @@
1
- import { G as GenericRequest, W as WithDripConfig, M as MiddlewareState, D as DripMiddlewareError, X as X402ResponseHeaders, a as X402PaymentRequest, b as X402PaymentProof } from './types-92iVqLtE.cjs';
2
- export { c as DripContext, d as DripMiddlewareErrorCode, R as ResponseBuilder } from './types-92iVqLtE.cjs';
3
- import Drip, { ChargeResult } from './index.cjs';
1
+ import { W as WithDripConfig, G as GenericRequest, X as X402ResponseHeaders, a as X402PaymentRequest, b as X402PaymentProof, M as MiddlewareState, D as DripMiddlewareError } from './types-Bo8SiUdl.cjs';
2
+ export { c as DripContext, d as DripMiddlewareErrorCode, R as ResponseBuilder } from './types-Bo8SiUdl.cjs';
3
+ import { Drip, ChargeResult } from './index.cjs';
4
4
  export { ChargeParams, ChargeStatus, Customer, DripConfig, DripError } from './index.cjs';
5
5
  export { DripRouteHandler, NextDripConfig, NextRequest, NextRouteHandler, createWithDrip, getDripHeader, hasPaymentProofHeaders as hasNextPaymentProof, withDrip } from './next.cjs';
6
6
  export { DripExpressRequest, ExpressDripConfig, ExpressMiddleware, ExpressNextFunction, ExpressRequest, ExpressResponse, createDripMiddleware, dripMiddleware, getDripContext, hasDripContext, hasPaymentProofHeaders as hasExpressPaymentProof } from './express.cjs';
@@ -1,6 +1,6 @@
1
- import { G as GenericRequest, W as WithDripConfig, M as MiddlewareState, D as DripMiddlewareError, X as X402ResponseHeaders, a as X402PaymentRequest, b as X402PaymentProof } from './types-D8mMON4v.js';
2
- export { c as DripContext, d as DripMiddlewareErrorCode, R as ResponseBuilder } from './types-D8mMON4v.js';
3
- import Drip, { ChargeResult } from './index.js';
1
+ import { W as WithDripConfig, G as GenericRequest, X as X402ResponseHeaders, a as X402PaymentRequest, b as X402PaymentProof, M as MiddlewareState, D as DripMiddlewareError } from './types-B2qwDadD.js';
2
+ export { c as DripContext, d as DripMiddlewareErrorCode, R as ResponseBuilder } from './types-B2qwDadD.js';
3
+ import { Drip, ChargeResult } from './index.js';
4
4
  export { ChargeParams, ChargeStatus, Customer, DripConfig, DripError } from './index.js';
5
5
  export { DripRouteHandler, NextDripConfig, NextRequest, NextRouteHandler, createWithDrip, getDripHeader, hasPaymentProofHeaders as hasNextPaymentProof, withDrip } from './next.js';
6
6
  export { DripExpressRequest, ExpressDripConfig, ExpressMiddleware, ExpressNextFunction, ExpressRequest, ExpressResponse, createDripMiddleware, dripMiddleware, getDripContext, hasDripContext, hasPaymentProofHeaders as hasExpressPaymentProof } from './express.js';
@@ -1,3 +1,3 @@
1
- import {randomBytes}from'crypto';var q=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var f=class t extends Error{constructor(r,s,i,n){super(r);this.code=s;this.statusCode=i;this.details=n;this.name="DripMiddlewareError",Object.setPrototypeOf(this,t.prototype);}};var E=class{_total=0;_flushed=false;_flushCount=0;_chargeFn;_options;constructor(e,r){this._chargeFn=e,this._options=r;}get total(){return this._total}get isFlushed(){return this._flushed}get flushCount(){return this._flushCount}async add(e){return e<=0?null:(this._total+=e,this._options.onAdd?.(e,this._total),this._options.flushThreshold!==void 0&&this._total>=this._options.flushThreshold?this.flush():null)}addSync(e){e<=0||(this._total+=e,this._options.onAdd?.(e,this._total));}async flush(){let e=this._total;if(this._total=0,e===0)return {success:true,quantity:0,charge:null,isReplay:false};let r=this._options.idempotencyKey?`${this._options.idempotencyKey}_flush_${this._flushCount}`:void 0,s=await this._chargeFn({customerId:this._options.customerId,meter:this._options.meter,quantity:e,idempotencyKey:r,metadata:this._options.metadata});this._flushed=true,this._flushCount++;let i={success:s.success,quantity:e,charge:s.charge,isReplay:s.isReplay};return this._options.onFlush?.(i),i}reset(){this._total=0;}};var k={maxAttempts:3,baseDelayMs:100,maxDelayMs:5e3};function X(t){return t instanceof Error&&(t.message.includes("fetch")||t.message.includes("network"))?true:t instanceof R?t.statusCode>=500||t.statusCode===408||t.statusCode===429:false}async function j(t,e={}){let r=e.maxAttempts??k.maxAttempts,s=e.baseDelayMs??k.baseDelayMs,i=e.maxDelayMs??k.maxDelayMs,n=e.isRetryable??X,o;for(let u=1;u<=r;u++)try{return await t()}catch(d){if(o=d,u===r||!n(d))throw d;let m=Math.min(s*Math.pow(2,u-1)+Math.random()*100,i);await new Promise(a=>setTimeout(a,m));}throw o}var R=class t extends Error{constructor(r,s,i){super(r);this.statusCode=s;this.code=i;this.name="DripError",Object.setPrototypeOf(this,t.prototype);}},I=class{apiKey;baseUrl;timeout;constructor(e){if(!e.apiKey)throw new Error("Drip API key is required");this.apiKey=e.apiKey,this.baseUrl=e.baseUrl||"https://api.drip.dev/v1",this.timeout=e.timeout||3e4;}async request(e,r={}){let s=new AbortController,i=setTimeout(()=>s.abort(),this.timeout);try{let n=await fetch(`${this.baseUrl}${e}`,{...r,signal:s.signal,headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,...r.headers}});if(n.status===204)return {success:!0};let o=await n.json();if(!n.ok)throw new R(o.message||o.error||"Request failed",n.status,o.code);return o}catch(n){throw n instanceof R?n:n instanceof Error&&n.name==="AbortError"?new R("Request timed out",408,"TIMEOUT"):new R(n instanceof Error?n.message:"Unknown error",0,"UNKNOWN")}finally{clearTimeout(i);}}async ping(){let e=new AbortController,r=setTimeout(()=>e.abort(),this.timeout),s=this.baseUrl;s.endsWith("/v1/")?s=s.slice(0,-4):s.endsWith("/v1")&&(s=s.slice(0,-3)),s=s.replace(/\/+$/,"");let i=Date.now();try{let n=await fetch(`${s}/health`,{signal:e.signal,headers:{Authorization:`Bearer ${this.apiKey}`}}),o=Date.now()-i,u="unknown",d=Date.now();try{let m=await n.json();typeof m.status=="string"&&(u=m.status),typeof m.timestamp=="number"&&(d=m.timestamp);}catch{u=n.ok?"healthy":`error:${n.status}`;}return !n.ok&&u==="unknown"&&(u=`error:${n.status}`),{ok:n.ok&&u==="healthy",status:u,latencyMs:o,timestamp:d}}catch(n){throw n instanceof Error&&n.name==="AbortError"?new R("Request timed out",408,"TIMEOUT"):new R(n instanceof Error?n.message:"Unknown error",0,"UNKNOWN")}finally{clearTimeout(r);}}async createCustomer(e){return this.request("/customers",{method:"POST",body:JSON.stringify(e)})}async getCustomer(e){return this.request(`/customers/${e}`)}async listCustomers(e){let r=new URLSearchParams;e?.limit&&r.set("limit",e.limit.toString()),e?.status&&r.set("status",e.status);let s=r.toString(),i=s?`/customers?${s}`:"/customers";return this.request(i)}async getBalance(e){return this.request(`/customers/${e}/balance`)}async charge(e){return this.request("/usage",{method:"POST",body:JSON.stringify({customerId:e.customerId,usageType:e.meter,quantity:e.quantity,idempotencyKey:e.idempotencyKey,metadata:e.metadata})})}async wrapApiCall(e){let r=e.idempotencyKey??`wrap_${Date.now()}_${Math.random().toString(36).slice(2,11)}`,s=await e.call(),i=e.extractUsage(s),n=await j(()=>this.charge({customerId:e.customerId,meter:e.meter,quantity:i,idempotencyKey:r,metadata:e.metadata}),e.retryOptions);return {result:s,charge:n,idempotencyKey:r}}async trackUsage(e){return this.request("/usage/internal",{method:"POST",body:JSON.stringify({customerId:e.customerId,usageType:e.meter,quantity:e.quantity,idempotencyKey:e.idempotencyKey,units:e.units,description:e.description,metadata:e.metadata})})}async getCharge(e){return this.request(`/charges/${e}`)}async listCharges(e){let r=new URLSearchParams;e?.customerId&&r.set("customerId",e.customerId),e?.status&&r.set("status",e.status),e?.limit&&r.set("limit",e.limit.toString()),e?.offset&&r.set("offset",e.offset.toString());let s=r.toString(),i=s?`/charges?${s}`:"/charges";return this.request(i)}async getChargeStatus(e){return this.request(`/charges/${e}/status`)}async checkout(e){let r=await this.request("/checkout",{method:"POST",body:JSON.stringify({customer_id:e.customerId,external_customer_id:e.externalCustomerId,amount:e.amount,return_url:e.returnUrl,cancel_url:e.cancelUrl,metadata:e.metadata})});return {id:r.id,url:r.url,expiresAt:r.expires_at,amountUsd:r.amount_usd}}async createWebhook(e){return this.request("/webhooks",{method:"POST",body:JSON.stringify(e)})}async listWebhooks(){return this.request("/webhooks")}async getWebhook(e){return this.request(`/webhooks/${e}`)}async deleteWebhook(e){return this.request(`/webhooks/${e}`,{method:"DELETE"})}async testWebhook(e){return this.request(`/webhooks/${e}/test`,{method:"POST"})}async rotateWebhookSecret(e){return this.request(`/webhooks/${e}/rotate-secret`,{method:"POST"})}async createWorkflow(e){return this.request("/workflows",{method:"POST",body:JSON.stringify(e)})}async listWorkflows(){return this.request("/workflows")}async startRun(e){return this.request("/runs",{method:"POST",body:JSON.stringify(e)})}async endRun(e,r){return this.request(`/runs/${e}`,{method:"PATCH",body:JSON.stringify(r)})}async getRunTimeline(e){return this.request(`/runs/${e}`)}async emitEvent(e){return this.request("/events",{method:"POST",body:JSON.stringify(e)})}async emitEventsBatch(e){return this.request("/run-events/batch",{method:"POST",body:JSON.stringify({events:e})})}async listMeters(){let e=await this.request("/pricing-plans");return {data:e.data.map(r=>({id:r.id,name:r.name,meter:r.unitType,unitPriceUsd:r.unitPriceUsd,isActive:r.isActive})),count:e.count}}async recordRun(e){let r=Date.now(),s=e.workflow,i=e.workflow;if(!e.workflow.startsWith("wf_"))try{let y=(await this.listWorkflows()).data.find(p=>p.slug===e.workflow||p.id===e.workflow);if(y)s=y.id,i=y.name;else {let p=await this.createWorkflow({name:e.workflow.replace(/[_-]/g," ").replace(/\b\w/g,x=>x.toUpperCase()),slug:e.workflow,productSurface:"AGENT"});s=p.id,i=p.name;}}catch{s=e.workflow;}let n=await this.startRun({customerId:e.customerId,workflowId:s,externalRunId:e.externalRunId,correlationId:e.correlationId,metadata:e.metadata}),o=0,u=0;if(e.events.length>0){let g=e.events.map((p,x)=>({runId:n.id,eventType:p.eventType,quantity:p.quantity,units:p.units,description:p.description,costUnits:p.costUnits,metadata:p.metadata,idempotencyKey:e.externalRunId?`${e.externalRunId}:${p.eventType}:${x}`:void 0})),y=await this.emitEventsBatch(g);o=y.created,u=y.duplicates;}let d=await this.endRun(n.id,{status:e.status,errorMessage:e.errorMessage,errorCode:e.errorCode}),m=Date.now()-r,a=e.events.length>0?`${o} events recorded`:"no events",l=`${e.status==="COMPLETED"?"\u2713":e.status==="FAILED"?"\u2717":"\u25CB"} ${i}: ${a} (${d.durationMs??m}ms)`;return {run:{id:n.id,workflowId:s,workflowName:i,status:e.status,durationMs:d.durationMs},events:{created:o,duplicates:u},totalCostUnits:d.totalCostUnits,summary:l}}static generateIdempotencyKey(e){let r=[e.customerId,e.runId??"no_run",e.stepName,String(e.sequence??0)],s=0,i=r.join("|");for(let n=0;n<i.length;n++){let o=i.charCodeAt(n);s=(s<<5)-s+o,s=s&s;}return `drip_${Math.abs(s).toString(36)}_${e.stepName.slice(0,16)}`}static async verifyWebhookSignature(e,r,s,i=300){if(!e||!r||!s)return false;try{let n=r.split(","),o=n.find(w=>w.startsWith("t=")),u=n.find(w=>w.startsWith("v1="));if(!o||!u)return !1;let d=parseInt(o.slice(2),10),m=u.slice(3);if(isNaN(d))return !1;let a=Math.floor(Date.now()/1e3);if(Math.abs(a-d)>i)return !1;let c=`${d}.${e}`,l=new TextEncoder,g=l.encode(s),y=l.encode(c),p=globalThis.crypto?.subtle??q("crypto").webcrypto.subtle,x=await p.importKey("raw",g,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),F=await p.sign("HMAC",x,y),A=Array.from(new Uint8Array(F)).map(w=>w.toString(16).padStart(2,"0")).join("");if(m.length!==A.length)return !1;let S=0;for(let w=0;w<m.length;w++)S|=m.charCodeAt(w)^A.charCodeAt(w);return S===0}catch{return false}}static verifyWebhookSignatureSync(e,r,s,i=300){if(!e||!r||!s)return false;try{let n=r.split(","),o=n.find(x=>x.startsWith("t=")),u=n.find(x=>x.startsWith("v1="));if(!o||!u)return !1;let d=parseInt(o.slice(2),10),m=u.slice(3);if(isNaN(d))return !1;let a=Math.floor(Date.now()/1e3);if(Math.abs(a-d)>i)return !1;let c=q("crypto"),l=`${d}.${e}`,g=c.createHmac("sha256",s).update(l).digest("hex"),y=Buffer.from(m),p=Buffer.from(g);return y.length!==p.length?!1:c.timingSafeEqual(y,p)}catch{return false}}static generateWebhookSignature(e,r,s){let i=q("crypto"),n=s??Math.floor(Date.now()/1e3),o=`${n}.${e}`,u=i.createHmac("sha256",r).update(o).digest("hex");return `t=${n},v1=${u}`}createStreamMeter(e){return new E(this.charge.bind(this),e)}};var B=300,J=300,Y=["x-payment-signature","x-payment-session-key","x-payment-smart-account","x-payment-timestamp","x-payment-amount","x-payment-recipient","x-payment-usage-id","x-payment-nonce"];function Q(t){return t.toLowerCase()}function h(t,e){let r=Q(e);if(t[r]!==void 0){let s=t[r];return Array.isArray(s)?s[0]:s}for(let[s,i]of Object.entries(t))if(s.toLowerCase()===r)return Array.isArray(i)?i[0]:i}function C(t){return Y.every(e=>h(t,e)!==void 0)}function M(t){let e=h(t,"x-payment-signature"),r=h(t,"x-payment-session-key"),s=h(t,"x-payment-smart-account"),i=h(t,"x-payment-timestamp"),n=h(t,"x-payment-amount"),o=h(t,"x-payment-recipient"),u=h(t,"x-payment-usage-id"),d=h(t,"x-payment-nonce");if(!e||!r||!s||!i||!n||!o||!u||!d)return null;let m=parseInt(i,10);if(isNaN(m)||Math.floor(Date.now()/1e3)-m>J)return null;let c=(l,g)=>{if(!l.startsWith("0x"))return false;let y=l.slice(2);return y.length<g?false:/^[a-fA-F0-9]+$/.test(y)};return !c(e,130)||!c(r,64)||!c(s,40)?null:{signature:e,sessionKeyId:r,smartAccount:s,timestamp:m,amount:n,recipient:o,usageId:u,nonce:d}}function N(t){let e=Math.floor(Date.now()/1e3),r=e+(t.expiresInSec??B),s=`${e}-${randomBytes(16).toString("hex")}`,i=t.usageId;i.startsWith("0x")||(i=_(i));let n={"X-Payment-Required":"true","X-Payment-Amount":t.amount,"X-Payment-Recipient":t.recipient,"X-Payment-Usage-Id":i,"X-Payment-Description":t.description??"API usage charge","X-Payment-Expires":String(r),"X-Payment-Nonce":s,"X-Payment-Timestamp":String(e)},o={amount:t.amount,recipient:t.recipient,usageId:i,description:t.description??"API usage charge",expiresAt:r,nonce:s,timestamp:e};return {headers:n,paymentRequest:o}}function _(t){let e=5381,r=52711;for(let n=0;n<t.length;n++){let o=t.charCodeAt(n);e=(e<<5)+e^o,r=(r<<5)+r^o;}return `0x${Math.abs(e*31+r).toString(16).padStart(16,"0").slice(0,16).padEnd(64,"0")}`}async function U(t,e){let r=e.customerResolver??"header";if(typeof r=="function")return r(t);if(r==="header"){let s=h(t.headers,"x-drip-customer-id")??h(t.headers,"x-customer-id");if(!s)throw new f("Missing customer ID. Include X-Drip-Customer-Id header.","CUSTOMER_RESOLUTION_FAILED",400);return s}if(r==="query"){let s=t.query??{},i=s.drip_customer_id??s.customer_id,n=Array.isArray(i)?i[0]:i;if(!n)throw new f("Missing customer ID. Include drip_customer_id query parameter.","CUSTOMER_RESOLUTION_FAILED",400);return n}throw new f(`Invalid customer resolver: ${r}`,"CONFIGURATION_ERROR",500)}async function O(t,e){return typeof e.quantity=="function"?e.quantity(t):e.quantity}async function W(t,e,r){if(r.idempotencyKey)return r.idempotencyKey(t);let s=Date.now(),i=[t.method,t.url,e,s];return `drip_${_(i.join("|")).slice(2,18)}`}function T(t){let e=t.apiKey??process.env.DRIP_API_KEY;if(!e)throw new f("Missing Drip API key. Set DRIP_API_KEY environment variable or pass apiKey in config.","CONFIGURATION_ERROR",500);return new I({apiKey:e,baseUrl:t.baseUrl??process.env.DRIP_API_URL})}async function D(t,e){if(e.skipInDevelopment&&process.env.NODE_ENV==="development"){console.warn("[Drip] Skipping billing in development mode. Set skipInDevelopment: false or NODE_ENV to production to enable billing.");let r=T(e),s={success:true,usageEventId:"dev_usage_event",isReplay:false,charge:{id:"dev_charge",amountUsdc:"0.00",amountToken:"0",txHash:"0x0",status:"CONFIRMED"}};return {success:true,state:{customerId:"dev_customer",quantity:typeof e.quantity=="number"?e.quantity:1,idempotencyKey:"dev_idempotency",hasPaymentProof:false},charge:s,drip:r,isReplay:false}}try{let r=T(e),s=await U(t,e),i=await O(t,e),n=await W(t,s,e),o=C(t.headers),u=o?M(t.headers):void 0,d={customerId:s,quantity:i,idempotencyKey:n,hasPaymentProof:o,paymentProof:u??void 0},m=typeof e.metadata=="function"?e.metadata(t):e.metadata;try{let a=await r.charge({customerId:s,meter:e.meter,quantity:i,idempotencyKey:n,metadata:m});return e.onCharge&&await e.onCharge(a,t),{success:!0,state:d,charge:a,drip:r,isReplay:a.isReplay??!1}}catch(a){if(a instanceof R){if(a.statusCode===402){let c=process.env.DRIP_RECIPIENT_ADDRESS;if(!c)throw new f("DRIP_RECIPIENT_ADDRESS environment variable must be configured for x402 payment flow.","CONFIGURATION_ERROR",500);let l="0.01",g=a.message.match(/amount[:\s]+([0-9.]+)/i);g?l=g[1]:l=(i*1e-4).toFixed(6);let{headers:y,paymentRequest:p}=N({amount:l,recipient:c,usageId:n,description:`${e.meter} usage charge`});return {success:!1,error:new f("Insufficient balance. Payment required.","PAYMENT_REQUIRED",402),paymentRequired:{headers:y,paymentRequest:p}}}throw e.onError&&await e.onError(a,t),new f(a.message,"CHARGE_FAILED",a.statusCode,{code:a.code})}throw a}}catch(r){if(r instanceof f)return {success:false,error:r};let s=r instanceof Error?r.message:"Unknown error";return {success:false,error:new f(s,"INTERNAL_ERROR",500)}}}function v(t){let e={};return t.forEach((r,s)=>{e[s.toLowerCase()]=r;}),e}function z(t){let e={};return t.forEach((r,s)=>{e[s]=r;}),e}function V(t,e,r,s){return Response.json({error:t,code:e,...s&&{details:s}},{status:r})}function Z(t,e){let r=new Headers;return Object.entries(t).forEach(([s,i])=>{r.set(s,i);}),r.set("Content-Type","application/json"),new Response(JSON.stringify({error:"Payment required",code:"PAYMENT_REQUIRED",paymentRequest:e,instructions:{step1:"Sign the payment request with your session key using EIP-712",step2:"Retry the request with X-Payment-* headers",documentation:"https://docs.drip.dev/x402"}}),{status:402,headers:r})}function K(t,e){return async(r,s)=>{let i={method:r.method,url:r.url,headers:v(r.headers),query:r.nextUrl?z(r.nextUrl.searchParams):{}},n=typeof t.quantity=="function"?await t.quantity(r):t.quantity,o;if(typeof t.customerResolver=="function"){let l=t.customerResolver;o=async()=>l(r);}else o=t.customerResolver;let u;if(typeof t.idempotencyKey=="function"){let l=t.idempotencyKey;u=async()=>l(r);}let d=typeof t.metadata=="function"?t.metadata(r):t.metadata,m={meter:t.meter,quantity:n,apiKey:t.apiKey,baseUrl:t.baseUrl,customerResolver:o,idempotencyKey:u,metadata:d,skipInDevelopment:t.skipInDevelopment,onCharge:void 0,onError:void 0},a=await D(i,m);if(!a.success){if(t.errorResponse){let l=await t.errorResponse(a.error,r);if(l)return l}return a.paymentRequired?Z(a.paymentRequired.headers,a.paymentRequired.paymentRequest):V(a.error.message,a.error.code,a.error.statusCode,a.error.details)}t.onCharge&&await t.onCharge(a.charge,r);let c={drip:a.drip,customerId:a.state.customerId,charge:a.charge,isReplay:a.isReplay,params:s?.params};try{return await e(r,c)}catch(l){throw l}}}function ee(t){return (e,r)=>K({...t,...e},r)}function te(t){return C(v(t.headers))}function re(t,e){return h(v(t.headers),e)}function L(t){let e={};for(let[r,s]of Object.entries(t))e[r.toLowerCase()]=Array.isArray(s)?s[0]:s;return e}function se(t,e,r){t.status(402).set(e).json({error:"Payment required",code:"PAYMENT_REQUIRED",paymentRequest:r,instructions:{step1:"Sign the payment request with your session key using EIP-712",step2:"Retry the request with X-Payment-* headers",documentation:"https://docs.drip.dev/x402"}});}function ne(t,e,r,s,i){t.status(s).json({error:e,code:r,...i&&{details:i}});}function H(t){let e=t.attachToRequest??true;return async(r,s,i)=>{let n={method:r.method,url:r.originalUrl||r.url,headers:L(r.headers),query:r.query},o=typeof t.quantity=="function"?await t.quantity(r):t.quantity,u;if(typeof t.customerResolver=="function"){let g=t.customerResolver;u=async()=>g(r);}else u=t.customerResolver;let d;if(typeof t.idempotencyKey=="function"){let g=t.idempotencyKey;d=async()=>g(r);}let m=typeof t.metadata=="function"?t.metadata(r):t.metadata,a={meter:t.meter,quantity:o,apiKey:t.apiKey,baseUrl:t.baseUrl,customerResolver:u,idempotencyKey:d,metadata:m,skipInDevelopment:t.skipInDevelopment,onCharge:void 0,onError:void 0},c=await D(n,a);if(!c.success){if(t.errorHandler&&await t.errorHandler(c.error,r,s))return;if(c.paymentRequired){se(s,c.paymentRequired.headers,c.paymentRequired.paymentRequest);return}ne(s,c.error.message,c.error.code,c.error.statusCode,c.error.details);return}t.onCharge&&await t.onCharge(c.charge,r);let l={drip:c.drip,customerId:c.state.customerId,charge:c.charge,isReplay:c.isReplay};e&&(r.drip=l),i();}}function ie(t){return e=>H({...t,...e})}function oe(t){return C(L(t.headers))}function $(t){return "drip"in t&&typeof t.drip=="object"}function ae(t){if(!$(t))throw new Error("Drip context not found on request. Ensure dripMiddleware is applied before this route.");return t.drip}
2
- export{I as Drip,R as DripError,f as DripMiddlewareError,T as createDripClient,ie as createDripMiddleware,ee as createWithDrip,H as dripMiddleware,W as generateIdempotencyKey,N as generatePaymentRequest,ae as getDripContext,re as getDripHeader,h as getHeader,$ as hasDripContext,oe as hasExpressPaymentProof,te as hasNextPaymentProof,C as hasPaymentProof,M as parsePaymentProof,D as processRequest,U as resolveCustomerId,O as resolveQuantity,K as withDrip};//# sourceMappingURL=middleware.js.map
1
+ import {randomBytes}from'crypto';var U=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var f=class r extends Error{constructor(t,s,n,i){super(t);this.code=s;this.statusCode=n;this.details=i;this.name="DripMiddlewareError",Object.setPrototypeOf(this,r.prototype);}};var D=class{_total=0;_flushed=false;_flushCount=0;_chargeFn;_options;constructor(e,t){this._chargeFn=e,this._options=t;}get total(){return this._total}get isFlushed(){return this._flushed}get flushCount(){return this._flushCount}async add(e){return e<=0?null:(this._total+=e,this._options.onAdd?.(e,this._total),this._options.flushThreshold!==void 0&&this._total>=this._options.flushThreshold?this.flush():null)}addSync(e){e<=0||(this._total+=e,this._options.onAdd?.(e,this._total));}async flush(){let e=this._total;if(this._total=0,e===0)return {success:true,quantity:0,charge:null,isReplay:false};let t=this._options.idempotencyKey?`${this._options.idempotencyKey}_flush_${this._flushCount}`:void 0,s=await this._chargeFn({customerId:this._options.customerId,meter:this._options.meter,quantity:e,idempotencyKey:t,metadata:this._options.metadata});this._flushed=true,this._flushCount++;let n={success:s.success,quantity:e,charge:s.charge,isReplay:s.isReplay};return this._options.onFlush?.(n),n}reset(){this._total=0;}};var ee={requestsPerSecond:100,burstSize:200,enabled:true},k=class{config;tokens;lastRefill;constructor(e){this.config={...ee,...e},this.tokens=this.config.burstSize,this.lastRefill=Date.now();}refill(){let e=Date.now(),t=(e-this.lastRefill)/1e3;this.tokens=Math.min(this.config.burstSize,this.tokens+t*this.config.requestsPerSecond),this.lastRefill=e;}async acquire(e){if(!this.config.enabled)return true;let t=e!==void 0?Date.now()+e:void 0;for(;;){if(this.refill(),this.tokens>=1)return this.tokens-=1,true;let s=(1-this.tokens)/this.config.requestsPerSecond*1e3;if(t!==void 0){let n=t-Date.now();if(n<=0)return false;await this.sleep(Math.min(s,n));}else await this.sleep(s);}}tryAcquire(){return this.config.enabled?(this.refill(),this.tokens>=1?(this.tokens-=1,true):false):true}get availableTokens(){return this.refill(),this.tokens}sleep(e){return new Promise(t=>setTimeout(t,e))}};var M=class r extends Error{attempts;lastError;constructor(e,t){super(`Retry exhausted after ${e} attempts: ${t.message}`),this.name="RetryExhaustedError",this.attempts=e,this.lastError=t,Object.setPrototypeOf(this,r.prototype);}};function H(r,e){let t=e.baseDelayMs*Math.pow(e.exponentialBase,r);if(t=Math.min(t,e.maxDelayMs),e.jitter>0){let s=t*e.jitter;t+=Math.random()*2*s-s;}return Math.max(0,t)}function B(r,e){if(r instanceof Error){if(r.message.includes("fetch")||r.message.includes("network")||r.message.includes("ECONNREFUSED")||r.message.includes("ETIMEDOUT"))return true;let t=r.statusCode;if(t!==void 0)return e.retryableStatusCodes.includes(t)}return false}var te={failureThreshold:5,successThreshold:2,timeoutMs:3e4,enabled:true},S=class r extends Error{circuitName;timeUntilRetryMs;constructor(e,t){super(`Circuit '${e}' is open. Retry in ${Math.round(t)}ms`),this.name="CircuitBreakerOpenError",this.circuitName=e,this.timeUntilRetryMs=t,Object.setPrototypeOf(this,r.prototype);}},v=class{name;config;state="closed";failureCount=0;successCount=0;lastFailureTime=null;constructor(e,t){this.name=e,this.config={...te,...t};}getState(){return this.checkStateTransition(),this.state}checkStateTransition(){this.state==="open"&&this.lastFailureTime!==null&&Date.now()-this.lastFailureTime>=this.config.timeoutMs&&(this.state="half_open",this.successCount=0);}recordSuccess(){this.config.enabled&&(this.state==="half_open"?(this.successCount+=1,this.successCount>=this.config.successThreshold&&(this.state="closed",this.failureCount=0)):this.state==="closed"&&(this.failureCount=0));}recordFailure(){this.config.enabled&&(this.failureCount+=1,this.lastFailureTime=Date.now(),this.state==="half_open"?this.state="open":this.state==="closed"&&this.failureCount>=this.config.failureThreshold&&(this.state="open"));}allowRequest(){return !this.config.enabled||(this.checkStateTransition(),this.state==="closed")?true:this.state==="half_open"}getTimeUntilRetry(){if(this.state!=="open"||this.lastFailureTime===null)return 0;let e=Date.now()-this.lastFailureTime;return Math.max(0,this.config.timeoutMs-e)}reset(){this.state="closed",this.failureCount=0,this.successCount=0,this.lastFailureTime=null;}},A=class{windowSize;metrics=[];totalRequests=0;totalSuccesses=0;totalFailures=0;constructor(e=1e3){this.windowSize=e;}record(e){for(this.metrics.push(e),this.totalRequests+=1,e.success?this.totalSuccesses+=1:this.totalFailures+=1;this.metrics.length>this.windowSize;)this.metrics.shift();}getSummary(){if(this.metrics.length===0)return {windowSize:0,totalRequests:0,totalSuccesses:0,totalFailures:0,successRate:0,avgLatencyMs:0,minLatencyMs:0,maxLatencyMs:0,p50LatencyMs:0,p95LatencyMs:0,p99LatencyMs:0,requestsByEndpoint:{},errorsByType:{}};let e=this.metrics.map(o=>o.durationMs).sort((o,u)=>o-u),t=this.metrics.filter(o=>o.success).length,s={};for(let o of this.metrics)s[o.endpoint]=(s[o.endpoint]??0)+1;let n={};for(let o of this.metrics)o.error&&(n[o.error]=(n[o.error]??0)+1);let i=e.reduce((o,u)=>o+u,0);return {windowSize:this.metrics.length,totalRequests:this.totalRequests,totalSuccesses:this.totalSuccesses,totalFailures:this.totalFailures,successRate:t/this.metrics.length*100,avgLatencyMs:i/e.length,minLatencyMs:e[0],maxLatencyMs:e[e.length-1],p50LatencyMs:e[Math.floor(e.length*.5)],p95LatencyMs:e[Math.floor(e.length*.95)],p99LatencyMs:e[Math.floor(e.length*.99)],requestsByEndpoint:s,errorsByType:n}}reset(){this.metrics.length=0,this.totalRequests=0,this.totalSuccesses=0,this.totalFailures=0;}};function P(){return {rateLimiter:{requestsPerSecond:100,burstSize:200,enabled:true},retry:{maxRetries:3,baseDelayMs:100,maxDelayMs:1e4,exponentialBase:2,jitter:.1,retryableStatusCodes:[429,500,502,503,504],enabled:true},circuitBreaker:{failureThreshold:5,successThreshold:2,timeoutMs:3e4,enabled:true},collectMetrics:true}}function N(){return {rateLimiter:{requestsPerSecond:1e3,burstSize:2e3,enabled:true},retry:{maxRetries:2,baseDelayMs:50,maxDelayMs:5e3,exponentialBase:2,jitter:.1,retryableStatusCodes:[429,500,502,503,504],enabled:true},circuitBreaker:{failureThreshold:10,successThreshold:3,timeoutMs:15e3,enabled:true},collectMetrics:true}}var E=class{config;rateLimiter;circuitBreaker;metrics;constructor(e){this.config={...P(),...e,rateLimiter:{...P().rateLimiter,...e?.rateLimiter},retry:{...P().retry,...e?.retry},circuitBreaker:{...P().circuitBreaker,...e?.circuitBreaker}},this.rateLimiter=new k(this.config.rateLimiter),this.circuitBreaker=new v("drip_api",this.config.circuitBreaker),this.metrics=this.config.collectMetrics?new A:null;}async execute(e,t="UNKNOWN",s="unknown"){let n=performance.now(),i=0,o=null;if(!await this.rateLimiter.acquire(3e4))throw new Error("Rate limiter timeout");if(!this.circuitBreaker.allowRequest())throw new S(this.circuitBreaker.name,this.circuitBreaker.getTimeUntilRetry());for(let c=0;c<=this.config.retry.maxRetries;c++)try{let l=await e();if(this.circuitBreaker.recordSuccess(),this.metrics){let a=performance.now()-n;this.metrics.record({method:t,endpoint:s,statusCode:200,durationMs:a,success:!0,timestamp:Date.now(),retryCount:i});}return l}catch(l){if(o=l instanceof Error?l:new Error(String(l)),this.config.retry.enabled&&B(l,this.config.retry)&&c<this.config.retry.maxRetries){i+=1;let d=H(c,this.config.retry);await this.sleep(d);continue}if(this.circuitBreaker.recordFailure(),this.metrics){let d=performance.now()-n,m=l.statusCode??null;this.metrics.record({method:t,endpoint:s,statusCode:m,durationMs:d,success:false,timestamp:Date.now(),error:o.name,retryCount:i});}throw l}throw o?new M(this.config.retry.maxRetries+1,o):new Error("Unexpected execution path")}getMetrics(){return this.metrics?.getSummary()??null}getHealth(){return {circuitBreaker:{state:this.circuitBreaker.getState(),timeUntilRetryMs:this.circuitBreaker.getTimeUntilRetry()},rateLimiter:{availableTokens:this.rateLimiter.availableTokens,requestsPerSecond:this.config.rateLimiter.requestsPerSecond},metrics:this.getMetrics()}}sleep(e){return new Promise(t=>setTimeout(t,e))}};var _={maxAttempts:3,baseDelayMs:100,maxDelayMs:5e3};function re(r){return r instanceof Error&&(r.message.includes("fetch")||r.message.includes("network"))?true:r instanceof R?r.statusCode>=500||r.statusCode===408||r.statusCode===429:false}async function se(r,e={}){let t=e.maxAttempts??_.maxAttempts,s=e.baseDelayMs??_.baseDelayMs,n=e.maxDelayMs??_.maxDelayMs,i=e.isRetryable??re,o;for(let u=1;u<=t;u++)try{return await r()}catch(c){if(o=c,u===t||!i(c))throw c;let l=Math.min(s*Math.pow(2,u-1)+Math.random()*100,n);await new Promise(a=>setTimeout(a,l));}throw o}var R=class r extends Error{constructor(t,s,n){super(t);this.statusCode=s;this.code=n;this.name="DripError",Object.setPrototypeOf(this,r.prototype);}},q=class{apiKey;baseUrl;timeout;resilience;constructor(e){if(!e.apiKey)throw new Error("Drip API key is required");this.apiKey=e.apiKey,this.baseUrl=e.baseUrl||"https://api.drip.dev/v1",this.timeout=e.timeout||3e4,e.resilience===true?this.resilience=new E(P()):e.resilience==="high-throughput"?this.resilience=new E(N()):e.resilience&&typeof e.resilience=="object"?this.resilience=new E(e.resilience):this.resilience=null;}async request(e,t={}){let s=(t.method??"GET").toUpperCase();return this.resilience?this.resilience.execute(()=>this.rawRequest(e,t),s,e):this.rawRequest(e,t)}async rawRequest(e,t={}){let s=new AbortController,n=setTimeout(()=>s.abort(),this.timeout);try{let i=await fetch(`${this.baseUrl}${e}`,{...t,signal:s.signal,headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,...t.headers}});if(i.status===204)return {success:!0};let o=await i.json();if(!i.ok)throw new R(o.message||o.error||"Request failed",i.status,o.code);return o}catch(i){throw i instanceof R?i:i instanceof Error&&i.name==="AbortError"?new R("Request timed out",408,"TIMEOUT"):new R(i instanceof Error?i.message:"Unknown error",0,"UNKNOWN")}finally{clearTimeout(n);}}async ping(){let e=new AbortController,t=setTimeout(()=>e.abort(),this.timeout),s=this.baseUrl;s.endsWith("/v1/")?s=s.slice(0,-4):s.endsWith("/v1")&&(s=s.slice(0,-3)),s=s.replace(/\/+$/,"");let n=Date.now();try{let i=await fetch(`${s}/health`,{signal:e.signal,headers:{Authorization:`Bearer ${this.apiKey}`}}),o=Date.now()-n,u="unknown",c=Date.now();try{let l=await i.json();typeof l.status=="string"&&(u=l.status),typeof l.timestamp=="number"&&(c=l.timestamp);}catch{u=i.ok?"healthy":`error:${i.status}`;}return !i.ok&&u==="unknown"&&(u=`error:${i.status}`),{ok:i.ok&&u==="healthy",status:u,latencyMs:o,timestamp:c}}catch(i){throw i instanceof Error&&i.name==="AbortError"?new R("Request timed out",408,"TIMEOUT"):new R(i instanceof Error?i.message:"Unknown error",0,"UNKNOWN")}finally{clearTimeout(t);}}getMetrics(){return this.resilience?.getMetrics()??null}getHealth(){return this.resilience?.getHealth()??null}async createCustomer(e){return this.request("/customers",{method:"POST",body:JSON.stringify(e)})}async getCustomer(e){return this.request(`/customers/${e}`)}async listCustomers(e){let t=new URLSearchParams;e?.limit&&t.set("limit",e.limit.toString()),e?.status&&t.set("status",e.status);let s=t.toString(),n=s?`/customers?${s}`:"/customers";return this.request(n)}async getBalance(e){return this.request(`/customers/${e}/balance`)}async charge(e){return this.request("/usage",{method:"POST",body:JSON.stringify({customerId:e.customerId,usageType:e.meter,quantity:e.quantity,idempotencyKey:e.idempotencyKey,metadata:e.metadata})})}async wrapApiCall(e){let t=e.idempotencyKey??`wrap_${Date.now()}_${Math.random().toString(36).slice(2,11)}`,s=await e.call(),n=e.extractUsage(s),i=await se(()=>this.charge({customerId:e.customerId,meter:e.meter,quantity:n,idempotencyKey:t,metadata:e.metadata}),e.retryOptions);return {result:s,charge:i,idempotencyKey:t}}async trackUsage(e){return this.request("/usage/internal",{method:"POST",body:JSON.stringify({customerId:e.customerId,usageType:e.meter,quantity:e.quantity,idempotencyKey:e.idempotencyKey,units:e.units,description:e.description,metadata:e.metadata})})}async getCharge(e){return this.request(`/charges/${e}`)}async listCharges(e){let t=new URLSearchParams;e?.customerId&&t.set("customerId",e.customerId),e?.status&&t.set("status",e.status),e?.limit&&t.set("limit",e.limit.toString()),e?.offset&&t.set("offset",e.offset.toString());let s=t.toString(),n=s?`/charges?${s}`:"/charges";return this.request(n)}async getChargeStatus(e){return this.request(`/charges/${e}/status`)}async checkout(e){let t=await this.request("/checkout",{method:"POST",body:JSON.stringify({customer_id:e.customerId,external_customer_id:e.externalCustomerId,amount:e.amount,return_url:e.returnUrl,cancel_url:e.cancelUrl,metadata:e.metadata})});return {id:t.id,url:t.url,expiresAt:t.expires_at,amountUsd:t.amount_usd}}async createWebhook(e){return this.request("/webhooks",{method:"POST",body:JSON.stringify(e)})}async listWebhooks(){return this.request("/webhooks")}async getWebhook(e){return this.request(`/webhooks/${e}`)}async deleteWebhook(e){return this.request(`/webhooks/${e}`,{method:"DELETE"})}async testWebhook(e){return this.request(`/webhooks/${e}/test`,{method:"POST"})}async rotateWebhookSecret(e){return this.request(`/webhooks/${e}/rotate-secret`,{method:"POST"})}async createWorkflow(e){return this.request("/workflows",{method:"POST",body:JSON.stringify(e)})}async listWorkflows(){return this.request("/workflows")}async startRun(e){return this.request("/runs",{method:"POST",body:JSON.stringify(e)})}async endRun(e,t){return this.request(`/runs/${e}`,{method:"PATCH",body:JSON.stringify(t)})}async getRunTimeline(e){return this.request(`/runs/${e}`)}async emitEvent(e){return this.request("/events",{method:"POST",body:JSON.stringify(e)})}async emitEventsBatch(e){return this.request("/run-events/batch",{method:"POST",body:JSON.stringify({events:e})})}async listMeters(){let e=await this.request("/pricing-plans");return {data:e.data.map(t=>({id:t.id,name:t.name,meter:t.unitType,unitPriceUsd:t.unitPriceUsd,isActive:t.isActive})),count:e.count}}async estimateFromUsage(e){let t=e.periodStart instanceof Date?e.periodStart.toISOString():e.periodStart,s=e.periodEnd instanceof Date?e.periodEnd.toISOString():e.periodEnd;return this.request("/dashboard/cost-estimate/from-usage",{method:"POST",body:JSON.stringify({customerId:e.customerId,periodStart:t,periodEnd:s,defaultUnitPrice:e.defaultUnitPrice,includeChargedEvents:e.includeChargedEvents,usageTypes:e.usageTypes,customPricing:e.customPricing})})}async estimateFromHypothetical(e){return this.request("/dashboard/cost-estimate/hypothetical",{method:"POST",body:JSON.stringify({items:e.items,defaultUnitPrice:e.defaultUnitPrice,customPricing:e.customPricing})})}async recordRun(e){let t=Date.now(),s=e.workflow,n=e.workflow;if(!e.workflow.startsWith("wf_"))try{let h=(await this.listWorkflows()).data.find(p=>p.slug===e.workflow||p.id===e.workflow);if(h)s=h.id,n=h.name;else {let p=await this.createWorkflow({name:e.workflow.replace(/[_-]/g," ").replace(/\b\w/g,b=>b.toUpperCase()),slug:e.workflow,productSurface:"AGENT"});s=p.id,n=p.name;}}catch{s=e.workflow;}let i=await this.startRun({customerId:e.customerId,workflowId:s,externalRunId:e.externalRunId,correlationId:e.correlationId,metadata:e.metadata}),o=0,u=0;if(e.events.length>0){let g=e.events.map((p,b)=>({runId:i.id,eventType:p.eventType,quantity:p.quantity,units:p.units,description:p.description,costUnits:p.costUnits,metadata:p.metadata,idempotencyKey:e.externalRunId?`${e.externalRunId}:${p.eventType}:${b}`:void 0})),h=await this.emitEventsBatch(g);o=h.created,u=h.duplicates;}let c=await this.endRun(i.id,{status:e.status,errorMessage:e.errorMessage,errorCode:e.errorCode}),l=Date.now()-t,a=e.events.length>0?`${o} events recorded`:"no events",m=`${e.status==="COMPLETED"?"\u2713":e.status==="FAILED"?"\u2717":"\u25CB"} ${n}: ${a} (${c.durationMs??l}ms)`;return {run:{id:i.id,workflowId:s,workflowName:n,status:e.status,durationMs:c.durationMs},events:{created:o,duplicates:u},totalCostUnits:c.totalCostUnits,summary:m}}static generateIdempotencyKey(e){let t=[e.customerId,e.runId??"no_run",e.stepName,String(e.sequence??0)],s=0,n=t.join("|");for(let i=0;i<n.length;i++){let o=n.charCodeAt(i);s=(s<<5)-s+o,s=s&s;}return `drip_${Math.abs(s).toString(36)}_${e.stepName.slice(0,16)}`}static async verifyWebhookSignature(e,t,s,n=300){if(!e||!t||!s)return false;try{let i=t.split(","),o=i.find(x=>x.startsWith("t=")),u=i.find(x=>x.startsWith("v1="));if(!o||!u)return !1;let c=parseInt(o.slice(2),10),l=u.slice(3);if(isNaN(c))return !1;let a=Math.floor(Date.now()/1e3);if(Math.abs(a-c)>n)return !1;let d=`${c}.${e}`,m=new TextEncoder,g=m.encode(s),h=m.encode(d),p=globalThis.crypto?.subtle??U("crypto").webcrypto.subtle,b=await p.importKey("raw",g,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),Z=await p.sign("HMAC",b,h),F=Array.from(new Uint8Array(Z)).map(x=>x.toString(16).padStart(2,"0")).join("");if(l.length!==F.length)return !1;let W=0;for(let x=0;x<l.length;x++)W|=l.charCodeAt(x)^F.charCodeAt(x);return W===0}catch{return false}}static verifyWebhookSignatureSync(e,t,s,n=300){if(!e||!t||!s)return false;try{let i=t.split(","),o=i.find(b=>b.startsWith("t=")),u=i.find(b=>b.startsWith("v1="));if(!o||!u)return !1;let c=parseInt(o.slice(2),10),l=u.slice(3);if(isNaN(c))return !1;let a=Math.floor(Date.now()/1e3);if(Math.abs(a-c)>n)return !1;let d=U("crypto"),m=`${c}.${e}`,g=d.createHmac("sha256",s).update(m).digest("hex"),h=Buffer.from(l),p=Buffer.from(g);return h.length!==p.length?!1:d.timingSafeEqual(h,p)}catch{return false}}static generateWebhookSignature(e,t,s){let n=U("crypto"),i=s??Math.floor(Date.now()/1e3),o=`${i}.${e}`,u=n.createHmac("sha256",t).update(o).digest("hex");return `t=${i},v1=${u}`}createStreamMeter(e){return new D(this.charge.bind(this),e)}};var ie=300,oe=300,ae=["x-payment-signature","x-payment-session-key","x-payment-smart-account","x-payment-timestamp","x-payment-amount","x-payment-recipient","x-payment-usage-id","x-payment-nonce"];function ue(r){return r.toLowerCase()}function y(r,e){let t=ue(e);if(r[t]!==void 0){let s=r[t];return Array.isArray(s)?s[0]:s}for(let[s,n]of Object.entries(r))if(s.toLowerCase()===t)return Array.isArray(n)?n[0]:n}function I(r){return ae.every(e=>y(r,e)!==void 0)}function K(r){let e=y(r,"x-payment-signature"),t=y(r,"x-payment-session-key"),s=y(r,"x-payment-smart-account"),n=y(r,"x-payment-timestamp"),i=y(r,"x-payment-amount"),o=y(r,"x-payment-recipient"),u=y(r,"x-payment-usage-id"),c=y(r,"x-payment-nonce");if(!e||!t||!s||!n||!i||!o||!u||!c)return null;let l=parseInt(n,10);if(isNaN(l)||Math.floor(Date.now()/1e3)-l>oe)return null;let d=(m,g)=>{if(!m.startsWith("0x"))return false;let h=m.slice(2);return h.length<g?false:/^[a-fA-F0-9]+$/.test(h)};return !d(e,130)||!d(t,64)||!d(s,40)?null:{signature:e,sessionKeyId:t,smartAccount:s,timestamp:l,amount:i,recipient:o,usageId:u,nonce:c}}function $(r){let e=Math.floor(Date.now()/1e3),t=e+(r.expiresInSec??ie),s=`${e}-${randomBytes(16).toString("hex")}`,n=r.usageId;n.startsWith("0x")||(n=j(n));let i={"X-Payment-Required":"true","X-Payment-Amount":r.amount,"X-Payment-Recipient":r.recipient,"X-Payment-Usage-Id":n,"X-Payment-Description":r.description??"API usage charge","X-Payment-Expires":String(t),"X-Payment-Nonce":s,"X-Payment-Timestamp":String(e)},o={amount:r.amount,recipient:r.recipient,usageId:n,description:r.description??"API usage charge",expiresAt:t,nonce:s,timestamp:e};return {headers:i,paymentRequest:o}}function j(r){let e=5381,t=52711;for(let i=0;i<r.length;i++){let o=r.charCodeAt(i);e=(e<<5)+e^o,t=(t<<5)+t^o;}return `0x${Math.abs(e*31+t).toString(16).padStart(16,"0").slice(0,16).padEnd(64,"0")}`}async function X(r,e){let t=e.customerResolver??"header";if(typeof t=="function")return t(r);if(t==="header"){let s=y(r.headers,"x-drip-customer-id")??y(r.headers,"x-customer-id");if(!s)throw new f("Missing customer ID. Include X-Drip-Customer-Id header.","CUSTOMER_RESOLUTION_FAILED",400);return s}if(t==="query"){let s=r.query??{},n=s.drip_customer_id??s.customer_id,i=Array.isArray(n)?n[0]:n;if(!i)throw new f("Missing customer ID. Include drip_customer_id query parameter.","CUSTOMER_RESOLUTION_FAILED",400);return i}throw new f(`Invalid customer resolver: ${t}`,"CONFIGURATION_ERROR",500)}async function G(r,e){return typeof e.quantity=="function"?e.quantity(r):e.quantity}async function z(r,e,t){if(t.idempotencyKey)return t.idempotencyKey(r);let s=Date.now(),n=[r.method,r.url,e,s];return `drip_${j(n.join("|")).slice(2,18)}`}function O(r){let e=r.apiKey??process.env.DRIP_API_KEY;if(!e)throw new f("Missing Drip API key. Set DRIP_API_KEY environment variable or pass apiKey in config.","CONFIGURATION_ERROR",500);return new q({apiKey:e,baseUrl:r.baseUrl??process.env.DRIP_API_URL})}async function T(r,e){if(e.skipInDevelopment&&process.env.NODE_ENV==="development"){console.warn("[Drip] Skipping billing in development mode. Set skipInDevelopment: false or NODE_ENV to production to enable billing.");let t=O(e),s={success:true,usageEventId:"dev_usage_event",isReplay:false,charge:{id:"dev_charge",amountUsdc:"0.00",amountToken:"0",txHash:"0x0",status:"CONFIRMED"}};return {success:true,state:{customerId:"dev_customer",quantity:typeof e.quantity=="number"?e.quantity:1,idempotencyKey:"dev_idempotency",hasPaymentProof:false},charge:s,drip:t,isReplay:false}}try{let t=O(e),s=await X(r,e),n=await G(r,e),i=await z(r,s,e),o=I(r.headers),u=o?K(r.headers):void 0,c={customerId:s,quantity:n,idempotencyKey:i,hasPaymentProof:o,paymentProof:u??void 0},l=typeof e.metadata=="function"?e.metadata(r):e.metadata;try{let a=await t.charge({customerId:s,meter:e.meter,quantity:n,idempotencyKey:i,metadata:l});return e.onCharge&&await e.onCharge(a,r),{success:!0,state:c,charge:a,drip:t,isReplay:a.isReplay??!1}}catch(a){if(a instanceof R){if(a.statusCode===402){let d=process.env.DRIP_RECIPIENT_ADDRESS;if(!d)throw new f("DRIP_RECIPIENT_ADDRESS environment variable must be configured for x402 payment flow.","CONFIGURATION_ERROR",500);let m="0.01",g=a.message.match(/amount[:\s]+([0-9.]+)/i);g?m=g[1]:m=(n*1e-4).toFixed(6);let{headers:h,paymentRequest:p}=$({amount:m,recipient:d,usageId:i,description:`${e.meter} usage charge`});return {success:!1,error:new f("Insufficient balance. Payment required.","PAYMENT_REQUIRED",402),paymentRequired:{headers:h,paymentRequest:p}}}throw e.onError&&await e.onError(a,r),new f(a.message,"CHARGE_FAILED",a.statusCode,{code:a.code})}throw a}}catch(t){if(t instanceof f)return {success:false,error:t};let s=t instanceof Error?t.message:"Unknown error";return {success:false,error:new f(s,"INTERNAL_ERROR",500)}}}function L(r){let e={};return r.forEach((t,s)=>{e[s.toLowerCase()]=t;}),e}function ce(r){let e={};return r.forEach((t,s)=>{e[s]=t;}),e}function le(r,e,t,s){return Response.json({error:r,code:e,...s&&{details:s}},{status:t})}function de(r,e){let t=new Headers;return Object.entries(r).forEach(([s,n])=>{t.set(s,n);}),t.set("Content-Type","application/json"),new Response(JSON.stringify({error:"Payment required",code:"PAYMENT_REQUIRED",paymentRequest:e,instructions:{step1:"Sign the payment request with your session key using EIP-712",step2:"Retry the request with X-Payment-* headers",documentation:"https://docs.drip.dev/x402"}}),{status:402,headers:t})}function J(r,e){return async(t,s)=>{let n={method:t.method,url:t.url,headers:L(t.headers),query:t.nextUrl?ce(t.nextUrl.searchParams):{}},i=typeof r.quantity=="function"?await r.quantity(t):r.quantity,o;if(typeof r.customerResolver=="function"){let m=r.customerResolver;o=async()=>m(t);}else o=r.customerResolver;let u;if(typeof r.idempotencyKey=="function"){let m=r.idempotencyKey;u=async()=>m(t);}let c=typeof r.metadata=="function"?r.metadata(t):r.metadata,l={meter:r.meter,quantity:i,apiKey:r.apiKey,baseUrl:r.baseUrl,customerResolver:o,idempotencyKey:u,metadata:c,skipInDevelopment:r.skipInDevelopment,onCharge:void 0,onError:void 0},a=await T(n,l);if(!a.success){if(r.errorResponse){let m=await r.errorResponse(a.error,t);if(m)return m}return a.paymentRequired?de(a.paymentRequired.headers,a.paymentRequired.paymentRequest):le(a.error.message,a.error.code,a.error.statusCode,a.error.details)}r.onCharge&&await r.onCharge(a.charge,t);let d={drip:a.drip,customerId:a.state.customerId,charge:a.charge,isReplay:a.isReplay,params:s?.params};try{return await e(t,d)}catch(m){throw m}}}function me(r){return (e,t)=>J({...r,...e},t)}function pe(r){return I(L(r.headers))}function ge(r,e){return y(L(r.headers),e)}function Y(r){let e={};for(let[t,s]of Object.entries(r))e[t.toLowerCase()]=Array.isArray(s)?s[0]:s;return e}function he(r,e,t){r.status(402).set(e).json({error:"Payment required",code:"PAYMENT_REQUIRED",paymentRequest:t,instructions:{step1:"Sign the payment request with your session key using EIP-712",step2:"Retry the request with X-Payment-* headers",documentation:"https://docs.drip.dev/x402"}});}function ye(r,e,t,s,n){r.status(s).json({error:e,code:t,...n&&{details:n}});}function Q(r){let e=r.attachToRequest??true;return async(t,s,n)=>{let i={method:t.method,url:t.originalUrl||t.url,headers:Y(t.headers),query:t.query},o=typeof r.quantity=="function"?await r.quantity(t):r.quantity,u;if(typeof r.customerResolver=="function"){let g=r.customerResolver;u=async()=>g(t);}else u=r.customerResolver;let c;if(typeof r.idempotencyKey=="function"){let g=r.idempotencyKey;c=async()=>g(t);}let l=typeof r.metadata=="function"?r.metadata(t):r.metadata,a={meter:r.meter,quantity:o,apiKey:r.apiKey,baseUrl:r.baseUrl,customerResolver:u,idempotencyKey:c,metadata:l,skipInDevelopment:r.skipInDevelopment,onCharge:void 0,onError:void 0},d=await T(i,a);if(!d.success){if(r.errorHandler&&await r.errorHandler(d.error,t,s))return;if(d.paymentRequired){he(s,d.paymentRequired.headers,d.paymentRequired.paymentRequest);return}ye(s,d.error.message,d.error.code,d.error.statusCode,d.error.details);return}r.onCharge&&await r.onCharge(d.charge,t);let m={drip:d.drip,customerId:d.state.customerId,charge:d.charge,isReplay:d.isReplay};e&&(t.drip=m),n();}}function fe(r){return e=>Q({...r,...e})}function Re(r){return I(Y(r.headers))}function V(r){return "drip"in r&&typeof r.drip=="object"}function be(r){if(!V(r))throw new Error("Drip context not found on request. Ensure dripMiddleware is applied before this route.");return r.drip}
2
+ export{q as Drip,R as DripError,f as DripMiddlewareError,O as createDripClient,fe as createDripMiddleware,me as createWithDrip,Q as dripMiddleware,z as generateIdempotencyKey,$ as generatePaymentRequest,be as getDripContext,ge as getDripHeader,y as getHeader,V as hasDripContext,Re as hasExpressPaymentProof,pe as hasNextPaymentProof,I as hasPaymentProof,K as parsePaymentProof,T as processRequest,X as resolveCustomerId,G as resolveQuantity,J as withDrip};//# sourceMappingURL=middleware.js.map
3
3
  //# sourceMappingURL=middleware.js.map