UNPKG

@dima_aryze/reforge

Version:

TypeScript/JavaScript SDK for Reforge - Cross-chain token operations

3 lines (2 loc) 18.5 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("axios")):"function"==typeof define&&define.amd?define(["exports","axios"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Reforge={},e.axios)}(this,function(e,t){"use strict";class r extends Error{constructor(e,t,i={}){super(e),Object.defineProperty(this,"cause",{enumerable:!0,configurable:!0,writable:!0,value:t}),Object.defineProperty(this,"name",{enumerable:!0,configurable:!0,writable:!0,value:"ReforgeError"}),Object.defineProperty(this,"isReforgeError",{enumerable:!0,configurable:!0,writable:!0,value:!0}),Object.defineProperty(this,"context",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.context={timestamp:new Date,...i},Error.captureStackTrace&&Error.captureStackTrace(this,r)}toJSON(){return{name:this.name,message:this.message,context:this.context,stack:this.stack}}getDetails(){return{...this.toJSON(),cause:this.cause?{name:this.cause.name,message:this.cause.message}:void 0}}}class i extends r{constructor(e,t,r,i,s,o={}){super(e,s,o),Object.defineProperty(this,"status",{enumerable:!0,configurable:!0,writable:!0,value:t}),Object.defineProperty(this,"code",{enumerable:!0,configurable:!0,writable:!0,value:r}),Object.defineProperty(this,"details",{enumerable:!0,configurable:!0,writable:!0,value:i}),Object.defineProperty(this,"name",{enumerable:!0,configurable:!0,writable:!0,value:"ReforgeApiError"})}static fromApiError(e,t,r){return new i(e.message,t||e.status||0,e.code,e.details,void 0,r)}isClientError(){return this.status>=400&&this.status<500}isServerError(){return this.status>=500&&this.status<600}hasCode(e){return this.code===e}isRateLimit(){return 429===this.status||this.hasCode("RATE_LIMIT")}isAuthenticationError(){return 401===this.status||this.hasCode("UNAUTHORIZED")}isAuthorizationError(){return 403===this.status||this.hasCode("FORBIDDEN")}toJSON(){return{...super.toJSON(),status:this.status,code:this.code,details:this.details}}}class s extends r{constructor(e,t,r,i,s={}){super(e,i,{...s,url:t}),Object.defineProperty(this,"url",{enumerable:!0,configurable:!0,writable:!0,value:t}),Object.defineProperty(this,"timeout",{enumerable:!0,configurable:!0,writable:!0,value:r}),Object.defineProperty(this,"name",{enumerable:!0,configurable:!0,writable:!0,value:"ReforgeNetworkError"})}static timeout(e,t){return new s("Request timed out",e,!0,void 0,t)}static connection(e,t,r){return new s("Network connection failed",e,!1,t,r)}static dnsResolution(e,t){return new s("DNS resolution failed",e,!1,void 0,t)}toJSON(){return{...super.toJSON(),url:this.url,timeout:this.timeout}}}class o extends r{constructor(e,t,r,i,s,o={}){super(e,s,o),Object.defineProperty(this,"field",{enumerable:!0,configurable:!0,writable:!0,value:t}),Object.defineProperty(this,"value",{enumerable:!0,configurable:!0,writable:!0,value:r}),Object.defineProperty(this,"constraint",{enumerable:!0,configurable:!0,writable:!0,value:i}),Object.defineProperty(this,"name",{enumerable:!0,configurable:!0,writable:!0,value:"ReforgeValidationError"})}static required(e,t){return new o(`Field '${e}' is required`,e,void 0,"required",void 0,t)}static invalid(e,t,r,i){return new o(`Invalid value for field '${e}': ${t}${r?`, expected ${r}`:""}`,e,t,"invalid",void 0,i)}static format(e,t,r,i){return new o(`Field '${e}' must be in ${r} format, got: ${t}`,e,t,`format:${r}`,void 0,i)}toJSON(){return{...super.toJSON(),field:this.field,value:this.value,constraint:this.constraint}}}class n extends r{constructor(e,t,r,i={}){super(e,r,i),Object.defineProperty(this,"configKey",{enumerable:!0,configurable:!0,writable:!0,value:t}),Object.defineProperty(this,"name",{enumerable:!0,configurable:!0,writable:!0,value:"ReforgeConfigurationError"})}static missing(e,t){return new n(`Configuration key '${e}' is missing or invalid`,e,void 0,t)}toJSON(){return{...super.toJSON(),configKey:this.configKey}}}class a extends r{constructor(e,t,r,i,s={}){super(e,i,s),Object.defineProperty(this,"operation",{enumerable:!0,configurable:!0,writable:!0,value:t}),Object.defineProperty(this,"operationData",{enumerable:!0,configurable:!0,writable:!0,value:r}),Object.defineProperty(this,"name",{enumerable:!0,configurable:!0,writable:!0,value:"ReforgeOperationError"})}static initiateFailed(e,t,r){return new a(`Reforge initiation failed: ${e}`,"initiate",t,void 0,r)}static finishFailed(e,t,r){return new a(`Reforge completion failed: ${e}`,"finish",t,void 0,r)}toJSON(){return{...super.toJSON(),operation:this.operation,operationData:this.operationData}}}const u={error:0,warn:1,info:2,debug:3};class c{constructor(e){Object.defineProperty(this,"config",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.config={level:e.level,prefix:e.prefix??"[REFORGE SDK]",timestamps:e.timestamps??!0,customLogger:e.customLogger}}shouldLog(e){return u[e]<=u[this.config.level]}formatMessage(e,t){return[this.config.timestamps?`[${(new Date).toISOString()}]`:"",this.config.prefix,`[${e.toUpperCase()}]`,t].filter(Boolean).join(" ")}error(e,...t){if(!this.shouldLog("error"))return;const r=this.formatMessage("error",e);this.config.customLogger?.error?this.config.customLogger.error(r,...t):console.error(r,...t)}warn(e,...t){if(!this.shouldLog("warn"))return;const r=this.formatMessage("warn",e);this.config.customLogger?.warn?this.config.customLogger.warn(r,...t):console.warn(r,...t)}info(e,...t){if(!this.shouldLog("info"))return;const r=this.formatMessage("info",e);this.config.customLogger?.info?this.config.customLogger.info(r,...t):console.info(r,...t)}debug(e,...t){if(!this.shouldLog("debug"))return;const r=this.formatMessage("debug",e);this.config.customLogger?.debug?this.config.customLogger.debug(r,...t):console.debug(r,...t)}setLevel(e){this.config.level=e}getLevel(){return this.config.level}child(e){return new c({...this.config,...e})}}function l(e="info",t){return new c({level:e,prefix:t})}function f(e){return new Promise(t=>setTimeout(t,e))}function g(e,t,r,i=2){const s=Math.min(t*Math.pow(i,e),r),o=Math.random()*s*.1;return Math.floor(s+o)}function h(e,...t){if(!t.length)return e;const r={...e};for(const e of t)if(d(e))for(const[t,i]of Object.entries(e))d(i)&&d(r[t])?r[t]=h(r[t],i):void 0!==i&&(r[t]=i);return r}function d(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function p(e){if(!e||"string"!=typeof e)throw new Error("URL must be a non-empty string");return e.replace(/\/+$/,"")}function m(){return`req_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}class b{transform(e){return e instanceof r?e:this.isTimeoutError(e)?s.timeout(e.config?.url):this.isConnectionError(e)?s.connection(e.config?.url,e):this.isHttpResponseError(e)?this.transformHttpError(e):this.isAxiosError(e)?this.transformAxiosError(e):new r(e?.message||"An unknown error occurred",e)}isTimeoutError(e){return"ECONNABORTED"===e.code||e.message&&e.message.includes("timeout")}isConnectionError(e){return"ENOTFOUND"===e.code||"ECONNREFUSED"===e.code||"ECONNRESET"===e.code||"ENETUNREACH"===e.code}isHttpResponseError(e){return e.response&&e.response.status}isAxiosError(e){return!0===e.isAxiosError}transformHttpError(e){const{status:t,data:r}=e.response;return r&&"object"==typeof r?this.createApiErrorFromResponse(r,t):new i(e.message||`HTTP ${t} Error`,t,`HTTP_${t}`,r)}transformAxiosError(e){return e.request&&!e.response?new s("No response received from server",e.config?.url,!1,e):new r(e.message||"Request configuration error",e)}createApiErrorFromResponse(e,t){if(this.isStandardApiError(e))return i.fromApiError(e,t);const r=this.extractErrorMessage(e),s=this.extractErrorCode(e,t),o=this.extractErrorDetails(e);return new i(r,t,s,o)}isStandardApiError(e){return e&&"object"==typeof e&&"string"==typeof e.code&&"string"==typeof e.message}extractErrorMessage(e){const t=["message","error","detail","description"];for(const r of t)if(e[r]&&"string"==typeof e[r])return e[r];if(Array.isArray(e.errors)&&e.errors.length>0){const t=e.errors[0];if("string"==typeof t)return t;if(t.message)return t.message}return"An API error occurred"}extractErrorCode(e,t){const r=["code","error_code","type","kind"];for(const t of r)if(e[t]&&"string"==typeof e[t])return e[t];return`HTTP_${t}`}extractErrorDetails(e){const{message:t,error:r,code:i,error_code:s,type:o,kind:n,...a}=e;return Object.keys(a).length>0?a:void 0}}class y{constructor(e,t){Object.defineProperty(this,"apiKey",{enumerable:!0,configurable:!0,writable:!0,value:e}),Object.defineProperty(this,"logger",{enumerable:!0,configurable:!0,writable:!0,value:t})}setup(e){e.interceptors.request.use(e=>this.handleRequest(e),e=>this.handleRequestError(e))}handleRequest(e){return this.apiKey&&!e.headers?.["skip-auth"]&&(e.headers={...e.headers,"x-api-key":this.apiKey}),e.headers?.["skip-auth"]&&delete e.headers["skip-auth"],e.headers?.["X-Request-ID"]||(e.headers={...e.headers,"X-Request-ID":m()}),e.headers={...e.headers,"X-Request-Timestamp":(new Date).toISOString()},this.logger?.debug("Outgoing request",{method:e.method?.toUpperCase(),url:e.url,baseURL:e.baseURL,headers:this.sanitizeHeaders(e.headers),hasData:!!e.data}),e}handleRequestError(e){return this.logger?.error("Request interceptor error",e),Promise.reject(e)}sanitizeHeaders(e){if(!e)return{};const t={...e},r=["x-api-key","authorization","cookie"];for(const e of r)t[e]&&(t[e]="[REDACTED]");return t}updateApiKey(e){this.apiKey=e}}class w{constructor(e,t){Object.defineProperty(this,"logger",{enumerable:!0,configurable:!0,writable:!0,value:t}),Object.defineProperty(this,"config",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.config={attempts:e.attempts??3,delay:e.delay??1e3,maxDelay:e.maxDelay??3e4,backoffMultiplier:e.backoffMultiplier??2}}async execute(e,t){const i=t?{...this.config,...t}:this.config;let s;const o=i.attempts;for(let t=0;t<o;t++)try{const r=await e(t);return t>0&&this.logger?.info(`Request succeeded after ${t+1} attempts`),r}catch(e){if(s=e instanceof r?e:new r(String(e)),t===o-1){this.logger?.error(`Request failed after ${o} attempts`,{error:s.message,finalAttempt:!0});break}if(!this.shouldRetry(s,t)){this.logger?.debug("Error is not retryable, stopping attempts",{error:s.message,attempt:t+1});break}const n=g(t,i.delay,i.maxDelay,i.backoffMultiplier);this.logger?.debug(`Retrying request after ${n}ms`,{attempt:t+1,maxAttempts:o,error:s.message,delay:n}),await f(n)}throw s}shouldRetry(e,t){return!(t>=this.config.attempts-1)&&("ReforgeNetworkError"===e.name||(e instanceof i?this.shouldRetryApiError(e):"ReforgeValidationError"!==e.name))}shouldRetryApiError(e){return!!e.isServerError()||!!e.isClientError()&&(!(!e.hasCode("RATE_LIMIT")&&429!==e.status)||408===e.status)}getConfig(){return{...this.config}}updateConfig(e){Object.assign(this.config,e)}calculateMaxRetryTime(){let e=0;for(let t=0;t<this.config.attempts-1;t++)e+=g(t,this.config.delay,this.config.maxDelay,this.config.backoffMultiplier);return e}child(e){return new w({...this.config,...e},this.logger)}}const v={timeout:3e4,headers:{},debug:!1,retry:{attempts:3,delay:1e3,maxDelay:3e4,backoffMultiplier:2}};class E{constructor(e){Object.defineProperty(this,"httpClient",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"config",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"logger",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"eventListeners",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"errorTransformer",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"retryHandler",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"apiKey",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.validateOptions(e),this.config=h({},v,{baseUrl:e.baseUrl,timeout:e.timeout,headers:e.headers,debug:e.debug,retry:e.retry}),this.apiKey=e.apiKey,this.logger=l(this.config.debug?"debug":"warn"),this.errorTransformer=new b,this.retryHandler=new w(this.config.retry,this.logger),this.httpClient=e.httpClient||this.createHttpClient(),this.logger.info("HTTP client initialized",{baseUrl:this.config.baseUrl,hasApiKey:!!this.apiKey,debug:this.config.debug})}validateOptions(e){if(!e.apiKey||"string"!=typeof e.apiKey)throw new o("API key is required and must be a string");if(!e.baseUrl||"string"!=typeof e.baseUrl)throw new o("Base URL is required and must be a string");try{new URL(e.baseUrl)}catch{throw new o("Base URL must be a valid URL")}}createHttpClient(){const e=t.create({baseURL:p(this.config.baseUrl),timeout:this.config.timeout,headers:{"Content-Type":"application/json","User-Agent":"reforge-sdk/1.0.0",...this.config.headers}});return new y(this.apiKey,this.logger).setup(e),e.interceptors.response.use(e=>(this.logger.debug("Response received",{status:e.status,url:e.config.url}),e),e=>{const t=this.errorTransformer.transform(e);return this.logger.error("Response error",t.message),Promise.reject(t)}),e}emitEvent(e,t){const r=this.eventListeners.get(e)||[],i={type:e,timestamp:new Date,data:t};r.forEach(e=>{try{e(i)}catch(e){this.logger.error("Event listener error",e)}})}async makeRequest(e,t,i,s={}){return this.retryHandler.execute(async o=>{this.emitEvent("request:start",{method:e,path:t,attempt:o});try{const r={method:e,url:t,timeout:s.timeout||this.config.timeout,headers:{...s.headers,...s.skipAuth?{"skip-auth":"true"}:{},"X-Request-ID":m()}};i&&("GET"===e?r.params=i:r.data=i);const n=await this.httpClient.request(r);return this.emitEvent("request:success",{method:e,path:t,attempt:o,status:n.status}),n.data}catch(i){const s=i instanceof r?i:this.errorTransformer.transform(i);throw this.emitEvent("request:error",{method:e,path:t,attempt:o,error:s}),s}},s.retry)}setApiKey(e){if("string"!=typeof e||!e.trim())throw new o("API key must be a non-empty string");this.apiKey=e.trim(),this.logger.info("API key updated")}getApiKey(){return this.apiKey}on(e,t){this.eventListeners.has(e)||this.eventListeners.set(e,[]),this.eventListeners.get(e).push(t)}off(e,t){const r=this.eventListeners.get(e);if(r){const e=r.indexOf(t);e>-1&&r.splice(e,1)}}removeAllListeners(e){e?this.eventListeners.delete(e):this.eventListeners.clear()}}class R extends E{constructor(e){super(e)}async get(e,t,r){return this.makeRequest("GET",e,t,r)}async post(e,t,r){return this.makeRequest("POST",e,t,r)}async put(e,t,r){return this.makeRequest("PUT",e,t,r)}async patch(e,t,r){return this.makeRequest("PATCH",e,t,r)}async delete(e,t){return this.makeRequest("DELETE",e,void 0,t)}async health(){return this.get("/health",void 0,{skipAuth:!0})}async version(){return this.get("/version",void 0,{skipAuth:!0})}}class O{constructor(e){Object.defineProperty(this,"client",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"isConfigured",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"logger",{enumerable:!0,configurable:!0,writable:!0,value:l("warn")}),e&&this.configure(e)}configure(e){this.validateConfig(e);try{this.client=new R({apiKey:e.apiKey,baseUrl:e.apiUrl,timeout:e.timeout||3e4,debug:e.debug||!1}),this.isConfigured=!0,this.logger.info("Reforge SDK configured successfully")}catch(e){throw new n("Failed to configure SDK",void 0,e instanceof Error?e:new Error(String(e)))}}validateConfig(e){if(!e)throw new n("Configuration object is required");if(!e.apiKey||"string"!=typeof e.apiKey)throw n.missing("apiKey");if(!e.apiUrl||"string"!=typeof e.apiUrl)throw n.missing("apiUrl");try{new URL(e.apiUrl)}catch{throw new n("apiUrl must be a valid URL","apiUrl")}}ensureConfigured(){if(!this.isConfigured||!this.client)throw new n('SDK not configured. Please call reforge.config({apiKey: "...", apiUrl: "..."}) first.')}async initiateReforge(e){this.ensureConfigured();try{const t=await this.client.post("/initiateReforge",e);return this.logger.info("Reforge initiation successful"),{data:t.data||{success:!0}}}catch(t){return this.handleOperationError(t,"initiate",e)}}async finishReforge(e){this.ensureConfigured();try{const t=await this.client.post("/finishReforge",e);return this.logger.info("Reforge completion successful"),{data:t.data||{success:!0}}}catch(t){return this.handleOperationError(t,"finish",e)}}handleOperationError(e,t,o){let n;return e instanceof i?n=e.details?.message||e.message||`Failed to ${t} reforge`:e instanceof s?n="Network connection failed":e instanceof r?n=e.message:(n=e instanceof Error?e.message:"An unexpected error occurred",a["initiate"===t?"initiateFailed":"finishFailed"](n,o)),this.logger.error(`Reforge ${t} failed`,{error:n,operation:t,hasData:!!o}),{error:n}}getClient(){return this.ensureConfigured(),this.client}setApiKey(e){this.ensureConfigured(),this.client.setApiKey(e)}getApiKey(){return this.ensureConfigured(),this.client.getApiKey()}isReady(){return this.isConfigured&&null!==this.client}async testConnection(){this.ensureConfigured();try{const e=Date.now();await this.client.health();return{connected:!0,latency:Date.now()-e}}catch(e){return this.logger.warn("Connection test failed",{error:e}),{connected:!1}}}}let A=null;function P(){return A||(A=new O),A}const C={initiateReforge:e=>P().initiateReforge(e),finishReforge:e=>P().finishReforge(e),config:e=>{A||(A=new O),A.configure(e)},create:e=>new O(e),getInstance:()=>P()};e.ReforgeApiError=i,e.ReforgeClient=R,e.ReforgeConfigurationError=n,e.ReforgeError=r,e.ReforgeNetworkError=s,e.ReforgeOperationError=a,e.ReforgeSDK=O,e.ReforgeValidationError=o,e.SDK_NAME="@aryze/reforge",e.VERSION="1.0.0",e.createLogger=l,e.debounce=function(e,t){let r=null;return(...i)=>{r&&clearTimeout(r),r=setTimeout(()=>e(...i),t)}},e.default=C,e.exponentialBackoff=g,e.formatError=function(e){return e instanceof Error?`${e.name}: ${e.message}${e.stack?`\n${e.stack}`:""}`:String(e)},e.generateRequestId=m,e.isBrowser=function(){return"undefined"!=typeof window&&void 0!==window.document},e.isNode=function(){return"undefined"!=typeof process&&!!process.versions?.node},e.isReforgeError=function(e){return e instanceof Error&&"isReforgeError"in e&&!0===e.isReforgeError},e.retry=async function(e,t=3,r=1e3){let i;for(let s=0;s<t;s++)try{return await e()}catch(e){if(i=e instanceof Error?e:new Error(String(e)),s===t-1)throw i;const o=g(s,r,3e4);await f(o)}throw i},e.sleep=f,e.throttle=function(e,t){let r=0;return(...i)=>{const s=Date.now();s-r>=t&&(r=s,e(...i))}},Object.defineProperty(e,"__esModule",{value:!0})}); //# sourceMappingURL=reforge.min.js.map