UNPKG

@subscribe.dev/client

Version:

JavaScript/TypeScript client for SubscribeDev API - A drop-in for AI generation across 100+ models with built-in billing and rate limiting

3 lines (2 loc) 13.1 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const k=require("p-queue"),x=require("p-retry");function O(p){return p&&p.__esModule&&Object.prototype.hasOwnProperty.call(p,"default")?p.default:p}var T={exports:{}};(function(p){var e=Object.prototype.hasOwnProperty,t="~";function s(){}Object.create&&(s.prototype=Object.create(null),new s().__proto__||(t=!1));function c(u,r,i){this.fn=u,this.context=r,this.once=i||!1}function o(u,r,i,a,g){if(typeof i!="function")throw new TypeError("The listener must be a function");var f=new c(i,a||u,g),d=t?t+r:r;return u._events[d]?u._events[d].fn?u._events[d]=[u._events[d],f]:u._events[d].push(f):(u._events[d]=f,u._eventsCount++),u}function m(u,r){--u._eventsCount===0?u._events=new s:delete u._events[r]}function l(){this._events=new s,this._eventsCount=0}l.prototype.eventNames=function(){var r=[],i,a;if(this._eventsCount===0)return r;for(a in i=this._events)e.call(i,a)&&r.push(t?a.slice(1):a);return Object.getOwnPropertySymbols?r.concat(Object.getOwnPropertySymbols(i)):r},l.prototype.listeners=function(r){var i=t?t+r:r,a=this._events[i];if(!a)return[];if(a.fn)return[a.fn];for(var g=0,f=a.length,d=new Array(f);g<f;g++)d[g]=a[g].fn;return d},l.prototype.listenerCount=function(r){var i=t?t+r:r,a=this._events[i];return a?a.fn?1:a.length:0},l.prototype.emit=function(r,i,a,g,f,d){var v=t?t+r:r;if(!this._events[v])return!1;var n=this._events[v],y=arguments.length,w,h;if(n.fn){switch(n.once&&this.removeListener(r,n.fn,void 0,!0),y){case 1:return n.fn.call(n.context),!0;case 2:return n.fn.call(n.context,i),!0;case 3:return n.fn.call(n.context,i,a),!0;case 4:return n.fn.call(n.context,i,a,g),!0;case 5:return n.fn.call(n.context,i,a,g,f),!0;case 6:return n.fn.call(n.context,i,a,g,f,d),!0}for(h=1,w=new Array(y-1);h<y;h++)w[h-1]=arguments[h];n.fn.apply(n.context,w)}else{var A=n.length,E;for(h=0;h<A;h++)switch(n[h].once&&this.removeListener(r,n[h].fn,void 0,!0),y){case 1:n[h].fn.call(n[h].context);break;case 2:n[h].fn.call(n[h].context,i);break;case 3:n[h].fn.call(n[h].context,i,a);break;case 4:n[h].fn.call(n[h].context,i,a,g);break;default:if(!w)for(E=1,w=new Array(y-1);E<y;E++)w[E-1]=arguments[E];n[h].fn.apply(n[h].context,w)}}return!0},l.prototype.on=function(r,i,a){return o(this,r,i,a,!1)},l.prototype.once=function(r,i,a){return o(this,r,i,a,!0)},l.prototype.removeListener=function(r,i,a,g){var f=t?t+r:r;if(!this._events[f])return this;if(!i)return m(this,f),this;var d=this._events[f];if(d.fn)d.fn===i&&(!g||d.once)&&(!a||d.context===a)&&m(this,f);else{for(var v=0,n=[],y=d.length;v<y;v++)(d[v].fn!==i||g&&!d[v].once||a&&d[v].context!==a)&&n.push(d[v]);n.length?this._events[f]=n.length===1?n[0]:n:m(this,f)}return this},l.prototype.removeAllListeners=function(r){var i;return r?(i=t?t+r:r,this._events[i]&&m(this,i)):(this._events=new s,this._eventsCount=0),this},l.prototype.off=l.prototype.removeListener,l.prototype.addListener=l.prototype.on,l.prefixed=t,l.EventEmitter=l,p.exports=l})(T);var L=T.exports;const I=O(L);class b extends Error{constructor(e,t,s,c,o){super(e),this.name="SubscribeDevError",this.code=t,this.statusCode=s,this.details=c,this.requestId=o}}class R extends b{constructor(e,t,s,c){super(e,"INSUFFICIENT_BALANCE",402,{remainingCredits:t,requiredCredits:s},c),this.name="InsufficientBalanceError"}}class D extends b{constructor(e,t,s,c){super(e,"RATE_LIMIT_EXCEEDED",429,{resetTime:t,retryAfter:s},c),this.name="RateLimitError",this.resetTime=t,this.retryAfter=s}}class C extends b{constructor(e,t){super(e,"AUTHENTICATION_FAILED",401,void 0,t),this.name="AuthenticationError"}}class U extends b{constructor(e,t){super(e,"ACCESS_DENIED",403,void 0,t),this.name="AccessDeniedError"}}class q extends b{constructor(e,t){super(e,"NOT_FOUND",404,void 0,t),this.name="NotFoundError"}}class S extends b{constructor(e,t,s){super(e,"VALIDATION_ERROR",400,t,s),this.name="ValidationError"}}class _ extends b{constructor(e,t){super(e,"USER_UNSUBSCRIBED",402,void 0,t),this.name="UnsubscribedError"}}class P extends I{constructor(e){if(super(),this.config={baseUrl:e.baseUrl||"https://subscribedev.volterapp-dev.com",timeout:e.timeout||3e5,maxRetries:e.maxRetries||2,debug:e.debug||!1,...e},this.queue=new k({concurrency:10,interval:6e4,intervalCap:60}),this.fetch=globalThis.fetch?.bind(globalThis),!this.fetch)throw new Error("fetch is not available. Please provide a fetch polyfill.");this.debug("SubscribeDevClient initialized",{baseUrl:this.config.baseUrl})}get pricingUrl(){return`${this.config.baseUrl}/subscribe`}async run(e,t){const{input:s,response_format:c}=t;this.debug("Starting prediction",{model:e,input:s,response_format:c});const o={model:e,input:t.input};t.response_format&&(o.response_format=t.response_format);const m=await this.makeRequest("POST","/v1/run",o);return this.debug("Prediction completed",{hasOutput:!!m.output}),this.emit("usage-changed",{operation:"run",model:e}),m}async createPrediction(e,t){return this.queue.add(async()=>await x(async()=>{const s={model:e,input:t.input};t.response_format&&(s.response_format=t.response_format);const c=await this.makeRequest("POST","/v1/run",s);this.emit("usage-changed",{operation:"createPrediction",model:e});const o=new Date().toISOString();return{id:`pred_${Math.random().toString(36).substring(2,15)}`,created_at:o,started_at:o,completed_at:o,status:"succeeded",input:t.input,output:c.output,urls:{get:`${this.config.baseUrl}/v1/predictions/pred_${Math.random().toString(36).substring(2,15)}`}}},{retries:this.config.maxRetries,onFailedAttempt:s=>{this.debug("Prediction creation failed, retrying",{attempt:s.attemptNumber,error:s.message})},shouldRetry:s=>!(s instanceof _),factor:1.5,minTimeout:500,maxTimeout:2e3}))}async getPrediction(e){return console.warn("[DEPRECATED] getPrediction() is deprecated. Predictions now complete synchronously in run()."),this.queue.add(async()=>{const t=await this.makeRequest("GET",`/v1/predictions/${e}`);return this.transformResponse(t)})}async cancelPrediction(e){return this.queue.add(async()=>{const t=await this.makeRequest("POST",`/v1/predictions/${e}/cancel`);return this.transformResponse(t)})}async waitForPrediction(e,t){console.warn("[DEPRECATED] waitForPrediction() is deprecated. Predictions now complete synchronously in run()."),this.debug("Waiting for prediction completion",{id:e});let s=0;const c=1800;for(;s<c;){const o=await this.getPrediction(e);if(t&&t(o),["succeeded","failed","canceled"].includes(o.status))return this.debug("Prediction completed",{id:e,status:o.status}),o;const m=Math.min(1e3+s*100,5e3);await new Promise(l=>setTimeout(l,m)),s++}throw new b("Prediction timeout - exceeded maximum wait time","PREDICTION_TIMEOUT",408)}async getBalance(){const t=(await this.makeRequest("GET","/v1/subscriptions/usage")).credits?.userBalance;return{allocatedCredits:t?.allocatedCredits||0,usedCredits:t?.usedCredits||0,remainingCredits:t?.remainingCredits||0}}async getTransactions(e={}){const t=new URLSearchParams;e.limit&&t.set("limit",e.limit.toString()),e.offset&&t.set("offset",e.offset.toString()),e.status&&t.set("status",e.status),e.model&&t.set("model",e.model),e.startDate&&t.set("start_date",e.startDate),e.endDate&&t.set("end_date",e.endDate);const s=`/v1/transactions${t.toString()?"?"+t.toString():""}`;return this.makeRequest("GET",s)}async getRateLimits(){return this.makeRequest("GET","/v1/rate-limits")}async getStorage(e={}){const t=new URLSearchParams;e.appVersion&&t.set("appVersion",e.appVersion);const s=`/v1/storage${t.toString()?"?"+t.toString():""}`;return this.makeRequest("GET",s)}async setStorage(e,t={}){const s=new URLSearchParams;t.appVersion&&s.set("appVersion",t.appVersion);const c=`/v1/storage${s.toString()?"?"+s.toString():""}`;return this.makeRequest("PUT",c,{sessionData:e})}async deleteStorage(e={}){const t=new URLSearchParams;e.appVersion&&t.set("appVersion",e.appVersion);const s=`/v1/storage${t.toString()?"?"+t.toString():""}`;await this.makeRequest("DELETE",s)}async persistSessionData(e={}){if(typeof globalThis<"u"&&typeof globalThis.localStorage>"u")throw new Error("persistSessionData is only available in browser environments");const t=await this.getStorage(e),s=`subscribeDev_session_${this.config.apiKey.slice(-8)}`;return globalThis.localStorage.setItem(s,JSON.stringify(t.sessionData)),t}async getSessionData(e={}){const s=(await this.getStorage(e)).sessionData||{};if(typeof globalThis<"u"&&typeof globalThis.localStorage<"u"){const c=`subscribeDev_session_${this.config.apiKey.slice(-8)}`;globalThis.localStorage.setItem(c,JSON.stringify(s))}return s}async getSubscriptionStatus(){if(console.log("[SubscribeDevClient] getSubscriptionStatus called"),!this.config.userKey)throw console.log("[SubscribeDevClient] No userKey provided, throwing ValidationError"),new S("User key is required to get subscription status. Provide userKey in client configuration.",{method:"getSubscriptionStatus"});console.log("[SubscribeDevClient] Making request to /v1/subscriptions/plan with userKey:",this.config.userKey.substring(0,10)+"...");try{const e=await this.makeRequest("GET","/v1/subscriptions/plan");console.log("[SubscribeDevClient] Received response:",{hasUserPlan:!!e.userPlan,planId:e.userPlan?.planId,status:e.userPlan?.status,hasPlanDetails:!!e.userPlan?.plan});const t=e.userPlan;if(!t||t.status==="none"||!t.plan)return console.log("[SubscribeDevClient] User has no active subscription, returning none status"),{hasActiveSubscription:!1,status:t?.status||"none"};const s={hasActiveSubscription:t.status==="active",plan:t.plan?{id:t.plan.id||t.planId,name:t.plan.name,price:t.plan.price,tokenLimit:t.plan.tokenLimit||t.plan.token_limit,subtitle:t.plan.subtitle,description:t.plan.description,features:t.plan.features}:void 0,status:t.status,startedAt:t.startedAt,endsAt:t.endsAt};return console.log("[SubscribeDevClient] Returning subscription status:",{hasActiveSubscription:s.hasActiveSubscription,status:s.status,planName:s.plan?.name}),s}catch(e){throw console.log("[SubscribeDevClient] Error in getSubscriptionStatus:",{errorType:e.constructor.name,message:e.message}),e}}async getSubscriptionPlans(){return this.makeRequest("GET","/v1/subscriptions/status")}async createCheckoutSession(e){if(!this.config.userKey)throw new S("User key is required to create checkout session. Provide userKey in client configuration.",{method:"createCheckoutSession"});return this.makeRequest("POST","/v1/subscriptions/checkout",e)}async signupForFree(e){if(!this.config.userKey)throw new S("User key is required to sign up for free plan. Provide userKey in client configuration.",{method:"signupForFree"});return this.makeRequest("POST","/v1/subscriptions/free-signup",e)}async cancelSubscription(e,t=!0){if(!this.config.userKey)throw new S("User key is required to cancel subscription. Provide userKey in client configuration.",{method:"cancelSubscription"});return this.makeRequest("POST",`/v1/subscriptions/cancel/${e}`,{cancelAtPeriodEnd:t})}async getUsageLimits(){if(!this.config.userKey)throw new S("User key is required to get usage limits. Provide userKey in client configuration.",{method:"getUsageLimits"});return this.makeRequest("GET","/v1/subscriptions/usage")}async getUsage(){return this.getUsageLimits()}async makeRequest(e,t,s){const c=`${this.config.baseUrl}${t}`,o={Authorization:`Bearer ${this.config.apiKey}`,"Content-Type":"application/json","User-Agent":"@subscribe.dev/client/0.1.0"};this.config.userKey&&(o["X-User-Token"]=this.config.userKey);const m={method:e,headers:o,signal:AbortSignal.timeout(this.config.timeout)};s&&["POST","PUT","PATCH"].includes(e)&&(m.body=JSON.stringify(s)),this.debug("Making request",{method:e,url:c,headers:{...o,Authorization:"[redacted]"}});const l=await this.fetch(c,m),u=await l.text();let r;try{r=u?JSON.parse(u):null}catch{r={error:{message:u}}}return l.ok||this.handleErrorResponse(l,r),this.debug("Request successful",{status:l.status,data:r}),r}handleErrorResponse(e,t){const s=e.headers.get("x-request-id")||void 0,c=t?.error||{},o=c.message||`HTTP ${e.status}`;switch(e.status){case 400:throw new S(o,c.details,s);case 401:throw new C(o,s);case 402:throw c.code==="USER_UNSUBSCRIBED"||o.toLowerCase().includes("unsubscribed")||o.toLowerCase().includes("subscription")?new _(o,s):new R(o,c.details?.remainingCredits,c.details?.requiredCredits,s);case 403:throw new U(o,s);case 404:throw new q(o,s);case 429:throw new D(o,c.details?.resetTime,c.details?.retryAfter,s);default:throw new b(o,c.code||"UNKNOWN_ERROR",e.status,c.details,s)}}transformResponse(e){return{id:e.id,version:e.version,created_at:e.created_at,started_at:e.started_at,completed_at:e.completed_at,status:e.status,input:e.input,output:e.output,error:e.error,logs:e.logs,metrics:e.metrics,urls:e.urls||void 0}}debug(e,t){this.config.debug&&console.log(`[SubscribeDevClient] ${e}`,t||"")}static create(e){return new P(e)}}exports.AccessDeniedError=U;exports.AuthenticationError=C;exports.InsufficientBalanceError=R;exports.NotFoundError=q;exports.RateLimitError=D;exports.SubscribeDevClient=P;exports.SubscribeDevError=b;exports.UnsubscribedError=_;exports.ValidationError=S; //# sourceMappingURL=index.cjs.map