@selvajs/compute 1.5.1 → 1.5.2-beta.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,3 +1,3 @@
1
1
  var S=Object.defineProperty;var $=(e,r,t)=>r in e?S(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var W=(e,r)=>{for(var t in r)S(e,t,{get:r[t],enumerable:!0})};var R=(e,r,t)=>$(e,typeof r!="symbol"?r+"":r,t);var a={NETWORK_ERROR:"NETWORK_ERROR",AUTH_ERROR:"AUTH_ERROR",VALIDATION_ERROR:"VALIDATION_ERROR",COMPUTATION_ERROR:"COMPUTATION_ERROR",TIMEOUT_ERROR:"TIMEOUT_ERROR",CORS_ERROR:"CORS_ERROR",UNKNOWN_ERROR:"UNKNOWN_ERROR",INVALID_STATE:"INVALID_STATE",INVALID_INPUT:"INVALID_INPUT",INVALID_CONFIG:"INVALID_CONFIG",BROWSER_ONLY:"BROWSER_ONLY",ENVIRONMENT_ERROR:"ENVIRONMENT_ERROR",ENCODING_ERROR:"ENCODING_ERROR"};var d=class e extends Error{constructor(t,n="UNKNOWN_ERROR",s){super(t);R(this,"code");R(this,"statusCode");R(this,"context");R(this,"originalError");this.name="RhinoComputeError",this.code=n,this.statusCode=s?.statusCode,this.context=s?.context,this.originalError=s?.originalError,"cause"in Error.prototype&&Object.defineProperty(this,"cause",{value:s?.originalError,enumerable:!0})}static validation(t,n,s){return new e(`Input "${t}": ${n}`,a.VALIDATION_ERROR,{context:{inputName:t,reason:n,...s}})}static missingValues(t,n,s){return new e(`Input "${t}" has no values defined${n?` (expected ${n})`:""}`,a.INVALID_INPUT,{context:{inputName:t,expectedType:n,...s}})}static invalidDefault(t,n,s,i){return new e(`ValueList input "${t}" default value "${n}" is not in available values`,a.VALIDATION_ERROR,{context:{inputName:t,defaultValue:n,availableValues:s,...i}})}static unknownParamType(t,n,s){return new e(`Unknown paramType: ${t}`,a.VALIDATION_ERROR,{context:{receivedParamType:t,paramName:n,...s}})}static invalidStructure(t,n,s){return new e(`Invalid input structure for "${t}" (expected ${n})`,a.INVALID_INPUT,{context:{inputName:t,expectedStructure:n,...s}})}};var v=class{debug(){}info(){}warn(){}error(){}},O=class{debug(r,...t){console.debug(r,...t)}info(r,...t){console.info(r,...t)}warn(r,...t){console.warn(r,...t)}error(r,...t){console.error(r,...t)}},b=new v;function p(){return b}function N(e){e===null?b=new v:"debug"in e&&"info"in e&&"warn"in e&&"error"in e?b=e:b=new O}function _(){N(new O)}var y={attempts:0,baseDelayMs:500,maxDelayMs:3e4,retryOn429:!0},I=new Set([502,503,504]);function k(e){return e?{attempts:e.attempts??y.attempts,baseDelayMs:e.baseDelayMs??y.baseDelayMs,maxDelayMs:e.maxDelayMs??y.maxDelayMs,retryOn429:e.retryOn429??y.retryOn429}:y}function M(e){if(!e)return null;let r=Number(e);if(Number.isFinite(r)&&r>=0)return r*1e3;let t=Date.parse(e);if(Number.isFinite(t)){let n=t-Date.now();return n>0?n:0}return null}function w(e,r){let t=r.baseDelayMs*Math.pow(2,e),n=Math.random()*r.baseDelayMs;return Math.min(t+n,r.maxDelayMs)}function x(e,r){return new Promise((t,n)=>{if(r?.aborted){n(new DOMException("Aborted","AbortError"));return}let s=setTimeout(()=>{r?.removeEventListener("abort",i),t()},e),i=()=>{clearTimeout(s),n(new DOMException("Aborted","AbortError"))};r?.addEventListener("abort",i,{once:!0})})}function L(e,r,t,n,s,i){let{status:c,statusText:o}=e,l={url:r,requestId:t,method:"POST",requestSize:n,serverUrl:s},u=i?` \u2014 ${i.slice(0,200)}`:"",m={401:{message:`HTTP ${c}: ${o}${u}`,code:a.AUTH_ERROR},403:{message:`HTTP ${c}: ${o}${u}`,code:a.AUTH_ERROR},404:{message:`Endpoint not found: ${r}`,code:a.NETWORK_ERROR},413:{message:`Request too large: ${(n/1024).toFixed(2)}KB`,code:a.VALIDATION_ERROR},429:{message:"Rate limit exceeded",code:a.NETWORK_ERROR},500:{message:`Server error: ${i||o}`,code:a.COMPUTATION_ERROR},502:{message:`Service unavailable: ${o}`,code:a.NETWORK_ERROR},503:{message:`Service unavailable: ${o}`,code:a.NETWORK_ERROR},504:{message:`Service unavailable: ${o}`,code:a.NETWORK_ERROR}}[c]||{message:`HTTP ${c}: ${o}`,code:a.UNKNOWN_ERROR};throw new d(m.message,m.code,{statusCode:c,context:l})}function D(e,r){let t=r.replace(/\/+$/,""),n=e.replace(/^\/+/,"");return`${t}/${n}`}function U(e){try{let r=new URL(e).host;return/^(localhost|127\.0\.0\.1|::1)(:\d+)?$/i.test(r)}catch{return/(localhost|127\.0\.0\.1)/i.test(e)}}function q(e,r){let t={"X-Request-ID":e,"Content-Type":"application/json",...r.authToken&&{Authorization:r.authToken},...r.apiKey&&{RhinoComputeKey:r.apiKey}};return!r.apiKey&&!U(r.serverUrl)&&p().warn(`\u26A0\uFE0F [Rhino Compute] Request [${e}] targets remote server (${r.serverUrl}) but no API key is configured. Requests may fail or be rate-limited.`),t}function K(){return`${Date.now()}-${Math.random().toString(36).substring(2,11)}`}function f(e,r){r&&p().debug(e)}function P(e,r){let t=[],n=()=>{};if(e&&t.push(e),r&&r>0)if(typeof AbortSignal<"u"&&typeof AbortSignal.timeout=="function")t.push(AbortSignal.timeout(r));else{let o=new AbortController,l=setTimeout(()=>o.abort(),r);n=()=>clearTimeout(l),t.push(o.signal)}if(t.length===0)return{signal:void 0,cleanup:n};if(t.length===1)return{signal:t[0],cleanup:n};if(typeof AbortSignal<"u"&&typeof AbortSignal.any=="function")return{signal:AbortSignal.any(t),cleanup:n};let s=new AbortController,i=()=>s.abort();for(let o of t){if(o.aborted){s.abort();break}o.addEventListener("abort",i,{once:!0})}let c=n;return n=()=>{c();for(let o of t)o.removeEventListener("abort",i)},{signal:s.signal,cleanup:n}}async function F(e,r,t,n,s,i,c){let o=Math.round(performance.now()-i);if(!e.ok){let l=await e.text();if(c&&(f(`\u274C Request [${t}] failed with HTTP ${e.status} in ${o}ms`,!0),f(` URL: ${r}`,!0),f(` Status: ${e.status} ${e.statusText}`,!0),l&&f(` Response body: ${l.substring(0,500)}${l.length>500?"...":""}`,!0)),e.status===500)try{let u=JSON.parse(l);if(u?.values&&(u.errors||u.warnings))return c&&(f(`\u26A0\uFE0F Request [${t}] completed with Grasshopper errors in ${o}ms`,!0),u.errors?.length>0&&f(` Errors: ${JSON.stringify(u.errors,null,2)}`,!0),u.warnings?.length>0&&f(` Warnings: ${JSON.stringify(u.warnings,null,2)}`,!0)),u;u?.Message?l=`${u.ExceptionType?u.ExceptionType+": ":""}${u.Message}
2
- ${u.StackTrace||""}`:u?.error&&(l=typeof u.error=="string"?u.error:JSON.stringify(u.error,null,2))}catch(u){c&&f(` Failed to parse error body as JSON: ${u}`,!0)}L(e,r,t,n,s,l)}f(`\u2705 Request [${t}] completed in ${o}ms`,c);try{return await e.json()}catch(l){throw new d("Failed to parse JSON response",a.NETWORK_ERROR,{statusCode:e.status,context:{url:r,requestId:t},originalError:l instanceof Error?l:new Error(String(l))})}}async function H(e,r,t,n){let{signal:s,cleanup:i}=P(e.config.signal,e.config.timeoutMs),c=performance.now();try{let o=await fetch(e.fullUrl,{method:"POST",body:e.body,headers:e.headers,signal:s});if((I.has(o.status)||r.retryOn429&&o.status===429)&&t<n-1){let m=M(o.headers.get("Retry-After"))??w(t,r);return await o.text().catch(()=>{}),{ok:!1,retry:!0,delayMs:m,cause:new d(`HTTP ${o.status} ${o.statusText} (will retry)`,a.NETWORK_ERROR,{statusCode:o.status,context:{requestId:e.requestId}})}}return{ok:!0,value:await F(o,e.fullUrl,e.requestId,e.requestSize,e.config.serverUrl,c,e.config.debug)}}catch(o){if(o instanceof Error&&(o.name==="AbortError"||o.name==="TimeoutError")){if(e.config.signal?.aborted===!0)return{ok:!1,retry:!1,cause:new d("Request aborted by caller",a.UNKNOWN_ERROR,{context:{endpoint:e.endpoint,requestId:e.requestId,requestSize:e.requestSize},originalError:o})};let u=new d(`Request timed out after ${e.config.timeoutMs}ms`,a.TIMEOUT_ERROR,{context:{serverUrl:e.config.serverUrl,timeoutMs:e.config.timeoutMs,url:e.fullUrl,requestId:e.requestId,endpoint:e.endpoint,requestSize:e.requestSize}});return t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:u}:{ok:!1,retry:!1,cause:u}}if(o instanceof TypeError){let l=new d(`Network error: ${o.message}`,a.NETWORK_ERROR,{context:{serverUrl:e.config.serverUrl,url:e.fullUrl,requestId:e.requestId,endpoint:e.endpoint,requestSize:e.requestSize},originalError:o});return t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:l}:{ok:!1,retry:!1,cause:l}}if(o instanceof d){let l=o.statusCode;return l!==void 0&&(I.has(l)||r.retryOn429&&l===429)&&t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:o}:{ok:!1,retry:!1,cause:o}}return{ok:!1,retry:!1,cause:new d(o instanceof Error?o.message:String(o),a.UNKNOWN_ERROR,{context:{endpoint:e.endpoint,requestId:e.requestId},originalError:o instanceof Error?o:new Error(String(o))})}}finally{i()}}async function V(e,r,t){let n=K(),s=JSON.stringify(r),i=s.length,c=D(e,t.serverUrl),o=q(n,t),l=k(t.retry),u=l.attempts+1;if(t.debug){let h=(i/1024).toFixed(2),g=i>1e5?"\u26A0\uFE0F":"\u{1F680}";f(`${g} Starting compute request [${n}]: ${e} (${h}KB)`,!0)}let T={endpoint:e,body:s,requestSize:i,fullUrl:c,requestId:n,headers:o,config:t},m=null;for(let h=0;h<u;h++){let g=await H(T,l,h,u);if(g.ok)return g.value;if(!g.retry)throw g.cause;m=g.cause,t.debug&&f(`\u{1F501} Request [${n}] retrying after ${g.delayMs}ms (attempt ${h+2}/${u}): ${g.cause.message}`,!0);try{await x(g.delayMs,t.signal)}catch{throw new d("Request aborted by caller",a.UNKNOWN_ERROR,{context:{endpoint:e,requestId:n,requestSize:i},originalError:m})}}throw m??new d("Unknown error after retries",a.UNKNOWN_ERROR,{context:{endpoint:e,requestId:n,requestSize:i}})}var E=class{constructor(r,t){R(this,"serverUrl");R(this,"apiKey");R(this,"disposed",!1);R(this,"activeMonitors",new Set);R(this,"activeTimeouts",new Set);if(!r?.trim())throw new d("serverUrl is required",a.INVALID_CONFIG,{context:{serverUrl:r}});if(!r.match(/^https?:\/\//))throw new d(`Invalid serverUrl: "${r}". Must start with "http://" or "https://". For example: "http://localhost:5000" or "https://example.com"`,a.INVALID_CONFIG,{context:{serverUrl:r}});try{new URL(r)}catch(n){throw new d(`Invalid serverUrl: "${r}". Must be a valid URL. Received error: ${n instanceof Error?n.message:String(n)}`,a.INVALID_CONFIG,{context:{serverUrl:r},originalError:n instanceof Error?n:void 0})}this.apiKey=t,this.serverUrl=r.replace(/\/+$/,"")}buildHeaders(){let r={"Content-Type":"application/json"};return this.apiKey&&(r.RhinoComputeKey=this.apiKey),r}async isServerOnline(){this.ensureNotDisposed();let r=`${this.serverUrl}/healthcheck`,t={headers:this.buildHeaders(),method:"GET"};try{return(await fetch(r,t)).ok}catch(n){return p().debug("[ComputeServerStats] Fetch error:",n),!1}}async getActiveChildren(){this.ensureNotDisposed();try{let r=await fetch(`${this.serverUrl}/activechildren`,{headers:this.buildHeaders()});if(!r.ok)return p().warn("[ComputeServerStats] Failed to fetch active children:",r.status),null;let t=await r.text(),n=parseInt(t.trim(),10);return isNaN(n)?(p().warn("[ComputeServerStats] Invalid active children response:",t),null):n}catch(r){return p().warn("[ComputeServerStats] Error fetching active children:",r),null}}async getVersion(){this.ensureNotDisposed();try{let r=await fetch(`${this.serverUrl}/version`,{headers:this.buildHeaders()});if(!r.ok)return p().warn("[ComputeServerStats] Failed to fetch version:",r.status),null;try{let t=await r.json();return{rhino:t.rhino??"",compute:t.compute??"",git_sha:t.git_sha??null}}catch{return{rhino:await r.text(),compute:"",git_sha:null}}}catch(r){return p().warn("[ComputeServerStats] Error fetching version:",r),null}}async getServerStats(){if(this.ensureNotDisposed(),!await this.isServerOnline())return{isOnline:!1};let[t,n]=await Promise.all([this.getVersion(),this.getActiveChildren()]);return{isOnline:!0,...t&&{version:t},...n!==null&&{activeChildren:n}}}monitor(r,t=5e3){this.ensureNotDisposed();let n=!0,s=null;p().info(`\u{1F504} Starting server stats monitoring every ${t}ms`);let i=async()=>{if(s!==null&&(this.activeTimeouts.delete(s),s=null),!(!n||this.disposed)){try{let o=await this.getServerStats();if(!n||this.disposed)return;try{r(o)}catch(l){p().error("[ComputeServerStats] Monitor callback threw:",l)}}catch(o){p().error("[ComputeServerStats] Failed to fetch stats during monitor:",o)}n&&!this.disposed&&(s=setTimeout(()=>{i()},t),this.activeTimeouts.add(s))}},c=()=>{n=!1,s!==null&&(clearTimeout(s),this.activeTimeouts.delete(s),s=null),this.activeMonitors.delete(c)};return this.activeMonitors.add(c),i(),c}async dispose(){if(!this.disposed){this.disposed=!0;for(let r of this.activeMonitors)r();this.activeMonitors.clear();for(let r of this.activeTimeouts)clearTimeout(r);this.activeTimeouts.clear()}}ensureNotDisposed(){if(this.disposed)throw new d("ComputeServerStats has been disposed and cannot be used",a.INVALID_STATE,{context:{disposed:this.disposed}})}};function A(e,r={}){let{preserveSpaces:t=!1}=r,n=e.trim();return t?(n=n.charAt(0).toLowerCase()+n.slice(1).replace(/[-_](.)/g,(s,i)=>i?i.toUpperCase():""),n):(n=n.replace(/^[A-Z]/,s=>s.toLowerCase()).replace(/[\s-_]+(.)?/g,(s,i)=>i?i.toUpperCase():""),n)}function C(e,r={}){return!e||typeof e!="object"?e:Array.isArray(e)?r.deep?e.map(t=>C(t,r)):e:Object.keys(e).reduce((t,n)=>{let s=A(n,{preserveSpaces:r.preserveSpaces}),i=e[n];return t[s]=r.deep?C(i,r):i,t},{})}export{W as a,R as b,a as c,d,p as e,N as f,_ as g,V as h,E as i,A as j,C as k};
3
- //# sourceMappingURL=chunk-VK2TSW7S.js.map
2
+ ${u.StackTrace||""}`:u?.error&&(l=typeof u.error=="string"?u.error:JSON.stringify(u.error,null,2))}catch(u){c&&f(` Failed to parse error body as JSON: ${u}`,!0)}L(e,r,t,n,s,l)}f(`\u2705 Request [${t}] completed in ${o}ms`,c);try{return await e.json()}catch(l){throw new d("Failed to parse JSON response",a.NETWORK_ERROR,{statusCode:e.status,context:{url:r,requestId:t},originalError:l instanceof Error?l:new Error(String(l))})}}async function H(e,r,t,n){let{signal:s,cleanup:i}=P(e.config.signal,e.config.timeoutMs),c=performance.now();try{let o=await fetch(e.fullUrl,{method:"POST",body:e.body,headers:e.headers,signal:s});if((I.has(o.status)||r.retryOn429&&o.status===429)&&t<n-1){let m=M(o.headers.get("Retry-After"))??w(t,r);return await o.text().catch(()=>{}),{ok:!1,retry:!0,delayMs:m,cause:new d(`HTTP ${o.status} ${o.statusText} (will retry)`,a.NETWORK_ERROR,{statusCode:o.status,context:{requestId:e.requestId}})}}return{ok:!0,value:await F(o,e.fullUrl,e.requestId,e.requestSize,e.config.serverUrl,c,e.config.debug)}}catch(o){if(o instanceof Error&&(o.name==="AbortError"||o.name==="TimeoutError")){if(e.config.signal?.aborted===!0)return{ok:!1,retry:!1,cause:new d("Request aborted by caller",a.UNKNOWN_ERROR,{context:{endpoint:e.endpoint,requestId:e.requestId,requestSize:e.requestSize},originalError:o})};let u=new d(`Request timed out after ${e.config.timeoutMs}ms`,a.TIMEOUT_ERROR,{context:{serverUrl:e.config.serverUrl,timeoutMs:e.config.timeoutMs,url:e.fullUrl,requestId:e.requestId,endpoint:e.endpoint,requestSize:e.requestSize}});return t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:u}:{ok:!1,retry:!1,cause:u}}if(o instanceof TypeError){let l=new d(`Network error: ${o.message}`,a.NETWORK_ERROR,{context:{serverUrl:e.config.serverUrl,url:e.fullUrl,requestId:e.requestId,endpoint:e.endpoint,requestSize:e.requestSize},originalError:o});return t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:l}:{ok:!1,retry:!1,cause:l}}if(o instanceof d){let l=o.statusCode;return l!==void 0&&(I.has(l)||r.retryOn429&&l===429)&&t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:o}:{ok:!1,retry:!1,cause:o}}return{ok:!1,retry:!1,cause:new d(o instanceof Error?o.message:String(o),a.UNKNOWN_ERROR,{context:{endpoint:e.endpoint,requestId:e.requestId},originalError:o instanceof Error?o:new Error(String(o))})}}finally{i()}}async function V(e,r,t){let n=K(),s=JSON.stringify(r),i=s.length,c=D(e,t.serverUrl),o=q(n,t),l=k(t.retry),u=l.attempts+1;if(t.debug){let h=(i/1024).toFixed(2),g=i>1e5?"\u26A0\uFE0F":"\u{1F680}";f(`${g} Starting compute request [${n}]: ${e} (${h}KB)`,!0)}let T={endpoint:e,body:s,requestSize:i,fullUrl:c,requestId:n,headers:o,config:t},m=null;for(let h=0;h<u;h++){let g=await H(T,l,h,u);if(g.ok)return g.value;if(!g.retry)throw g.cause;m=g.cause,t.debug&&f(`\u{1F501} Request [${n}] retrying after ${g.delayMs}ms (attempt ${h+2}/${u}): ${g.cause.message}`,!0);try{await x(g.delayMs,t.signal)}catch{throw new d("Request aborted by caller",a.UNKNOWN_ERROR,{context:{endpoint:e,requestId:n,requestSize:i},originalError:m})}}throw m??new d("Unknown error after retries",a.UNKNOWN_ERROR,{context:{endpoint:e,requestId:n,requestSize:i}})}var E=class{constructor(r,t){R(this,"serverUrl");R(this,"apiKey");R(this,"disposed",!1);R(this,"activeMonitors",new Set);R(this,"activeTimeouts",new Set);if(!r?.trim())throw new d("serverUrl is required",a.INVALID_CONFIG,{context:{serverUrl:r}});if(!r.match(/^https?:\/\//))throw new d(`Invalid serverUrl: "${r}". Must start with "http://" or "https://". For example: "http://localhost:5000" or "https://example.com"`,a.INVALID_CONFIG,{context:{serverUrl:r}});try{new URL(r)}catch(n){throw new d(`Invalid serverUrl: "${r}". Must be a valid URL. Received error: ${n instanceof Error?n.message:String(n)}`,a.INVALID_CONFIG,{context:{serverUrl:r},originalError:n instanceof Error?n:void 0})}this.apiKey=t,this.serverUrl=r.replace(/\/+$/,"")}buildHeaders(){let r={"Content-Type":"application/json"};return this.apiKey&&(r.RhinoComputeKey=this.apiKey),r}async isServerOnline(){this.ensureNotDisposed();let r=`${this.serverUrl}/healthcheck`,t={headers:this.buildHeaders(),method:"GET"};try{return(await fetch(r,t)).ok}catch(n){return p().debug("[ComputeServerStats] Fetch error:",n),!1}}async getActiveChildren(){this.ensureNotDisposed();try{let r=await fetch(`${this.serverUrl}/activechildren`,{headers:this.buildHeaders()});if(!r.ok)return p().warn("[ComputeServerStats] Failed to fetch active children:",r.status),null;let t=await r.text(),n=parseInt(t.trim(),10);return isNaN(n)?(p().warn("[ComputeServerStats] Invalid active children response:",t),null):n}catch(r){return p().warn("[ComputeServerStats] Error fetching active children:",r),null}}async getVersion(){this.ensureNotDisposed();try{let r=await fetch(`${this.serverUrl}/version`,{headers:this.buildHeaders()});if(!r.ok)return p().warn("[ComputeServerStats] Failed to fetch version:",r.status),null;let t=await r.text();try{let n=JSON.parse(t);return{rhino:n.rhino??"",compute:n.compute??"",git_sha:n.git_sha??null}}catch{return{rhino:t,compute:"",git_sha:null}}}catch(r){return p().warn("[ComputeServerStats] Error fetching version:",r),null}}async getServerStats(){if(this.ensureNotDisposed(),!await this.isServerOnline())return{isOnline:!1};let[t,n]=await Promise.all([this.getVersion(),this.getActiveChildren()]);return{isOnline:!0,...t&&{version:t},...n!==null&&{activeChildren:n}}}monitor(r,t=5e3){this.ensureNotDisposed();let n=!0,s=null;p().info(`\u{1F504} Starting server stats monitoring every ${t}ms`);let i=async()=>{if(s!==null&&(this.activeTimeouts.delete(s),s=null),!(!n||this.disposed)){try{let o=await this.getServerStats();if(!n||this.disposed)return;try{r(o)}catch(l){p().error("[ComputeServerStats] Monitor callback threw:",l)}}catch(o){p().error("[ComputeServerStats] Failed to fetch stats during monitor:",o)}n&&!this.disposed&&(s=setTimeout(()=>{i()},t),this.activeTimeouts.add(s))}},c=()=>{n=!1,s!==null&&(clearTimeout(s),this.activeTimeouts.delete(s),s=null),this.activeMonitors.delete(c)};return this.activeMonitors.add(c),i(),c}async dispose(){if(!this.disposed){this.disposed=!0;for(let r of this.activeMonitors)r();this.activeMonitors.clear();for(let r of this.activeTimeouts)clearTimeout(r);this.activeTimeouts.clear()}}ensureNotDisposed(){if(this.disposed)throw new d("ComputeServerStats has been disposed and cannot be used",a.INVALID_STATE,{context:{disposed:this.disposed}})}};function A(e,r={}){let{preserveSpaces:t=!1}=r,n=e.trim();return t?(n=n.charAt(0).toLowerCase()+n.slice(1).replace(/[-_](.)/g,(s,i)=>i?i.toUpperCase():""),n):(n=n.replace(/^[A-Z]/,s=>s.toLowerCase()).replace(/[\s-_]+(.)?/g,(s,i)=>i?i.toUpperCase():""),n)}function C(e,r={}){return!e||typeof e!="object"?e:Array.isArray(e)?r.deep?e.map(t=>C(t,r)):e:Object.keys(e).reduce((t,n)=>{let s=A(n,{preserveSpaces:r.preserveSpaces}),i=e[n];return t[s]=r.deep?C(i,r):i,t},{})}export{W as a,R as b,a as c,d,p as e,N as f,_ as g,V as h,E as i,A as j,C as k};
3
+ //# sourceMappingURL=chunk-CZCPL35F.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/errors/error-codes.ts","../src/core/errors/base.ts","../src/core/utils/logger.ts","../src/core/compute-fetch/compute-fetch.ts","../src/core/server/compute-server-stats.ts","../src/core/utils/camel-case.ts"],"sourcesContent":["export const ErrorCodes = {\n\tNETWORK_ERROR: 'NETWORK_ERROR',\n\tAUTH_ERROR: 'AUTH_ERROR',\n\tVALIDATION_ERROR: 'VALIDATION_ERROR',\n\tCOMPUTATION_ERROR: 'COMPUTATION_ERROR',\n\tTIMEOUT_ERROR: 'TIMEOUT_ERROR',\n\tCORS_ERROR: 'CORS_ERROR',\n\tUNKNOWN_ERROR: 'UNKNOWN_ERROR',\n\tINVALID_STATE: 'INVALID_STATE',\n\tINVALID_INPUT: 'INVALID_INPUT',\n\tINVALID_CONFIG: 'INVALID_CONFIG',\n\tBROWSER_ONLY: 'BROWSER_ONLY',\n\tENVIRONMENT_ERROR: 'ENVIRONMENT_ERROR',\n\tENCODING_ERROR: 'ENCODING_ERROR'\n} as const;\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n","import { ErrorCodes } from './error-codes';\n\n/**\n * Simplified error for Rhino Compute operations\n *\n * @public Use this for error handling with error codes and context.\n */\nexport class RhinoComputeError extends Error {\n\tpublic readonly code: string;\n\tpublic readonly statusCode?: number;\n\tpublic readonly context?: Record<string, unknown>;\n\tpublic readonly originalError?: Error;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tcode: string = 'UNKNOWN_ERROR',\n\t\toptions?: { statusCode?: number; context?: Record<string, unknown>; originalError?: Error }\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'RhinoComputeError';\n\t\tthis.code = code;\n\t\tthis.statusCode = options?.statusCode;\n\t\tthis.context = options?.context;\n\t\tthis.originalError = options?.originalError;\n\n\t\t// Support error chaining (Node.js 16.9+, TypeScript 4.6+)\n\t\tif ('cause' in Error.prototype) {\n\t\t\tObject.defineProperty(this, 'cause', {\n\t\t\t\tvalue: options?.originalError,\n\t\t\t\tenumerable: true\n\t\t\t});\n\t\t}\n\t}\n\n\t// ============================================================================\n\t// Static Validation Error Helpers\n\t// ============================================================================\n\n\t/**\n\t * Create a generic validation error with custom reason\n\t */\n\tstatic validation(inputName: string, reason: string, context?: Record<string, unknown>) {\n\t\treturn new RhinoComputeError(`Input \"${inputName}\": ${reason}`, ErrorCodes.VALIDATION_ERROR, {\n\t\t\tcontext: { inputName, reason, ...context }\n\t\t});\n\t}\n\n\t/**\n\t * Create an error for missing/empty values\n\t */\n\tstatic missingValues(inputName: string, expectedType?: string, context?: Record<string, unknown>) {\n\t\treturn new RhinoComputeError(\n\t\t\t`Input \"${inputName}\" has no values defined${expectedType ? ` (expected ${expectedType})` : ''}`,\n\t\t\tErrorCodes.INVALID_INPUT,\n\t\t\t{ context: { inputName, expectedType, ...context } }\n\t\t);\n\t}\n\n\t/**\n\t * Create an error for invalid default value in value list\n\t */\n\tstatic invalidDefault(\n\t\tinputName: string,\n\t\tdefaultValue: unknown,\n\t\tavailableValues: unknown[],\n\t\tcontext?: Record<string, unknown>\n\t) {\n\t\treturn new RhinoComputeError(\n\t\t\t`ValueList input \"${inputName}\" default value \"${defaultValue}\" is not in available values`,\n\t\t\tErrorCodes.VALIDATION_ERROR,\n\t\t\t{ context: { inputName, defaultValue, availableValues, ...context } }\n\t\t);\n\t}\n\n\t/**\n\t * Create an error for unknown parameter type\n\t */\n\tstatic unknownParamType(paramType: string, paramName?: string, context?: Record<string, unknown>) {\n\t\treturn new RhinoComputeError(`Unknown paramType: ${paramType}`, ErrorCodes.VALIDATION_ERROR, {\n\t\t\tcontext: { receivedParamType: paramType, paramName, ...context }\n\t\t});\n\t}\n\n\t/**\n\t * Create an error for invalid input structure\n\t */\n\tstatic invalidStructure(\n\t\tinputName: string,\n\t\texpectedStructure: string,\n\t\tcontext?: Record<string, unknown>\n\t) {\n\t\treturn new RhinoComputeError(\n\t\t\t`Invalid input structure for \"${inputName}\" (expected ${expectedStructure})`,\n\t\t\tErrorCodes.INVALID_INPUT,\n\t\t\t{ context: { inputName, expectedStructure, ...context } }\n\t\t);\n\t}\n}\n","/**\n * Logger interface for structured logging\n *\n * @public Implement this interface to provide custom logging behavior.\n */\nexport interface Logger {\n\tdebug(message: string, ...args: unknown[]): void;\n\tinfo(message: string, ...args: unknown[]): void;\n\twarn(message: string, ...args: unknown[]): void;\n\terror(message: string, ...args: unknown[]): void;\n}\n\n/**\n * No-op logger implementation (default)\n * @internal\n */\nclass NoOpLogger implements Logger {\n\tdebug(): void {}\n\tinfo(): void {}\n\twarn(): void {}\n\terror(): void {}\n}\n\n/**\n * Console logger implementation\n * @internal\n */\nclass ConsoleLogger implements Logger {\n\tdebug(message: string, ...args: unknown[]): void {\n\t\tconsole.debug(message, ...args);\n\t}\n\n\tinfo(message: string, ...args: unknown[]): void {\n\t\tconsole.info(message, ...args);\n\t}\n\n\twarn(message: string, ...args: unknown[]): void {\n\t\tconsole.warn(message, ...args);\n\t}\n\n\terror(message: string, ...args: unknown[]): void {\n\t\tconsole.error(message, ...args);\n\t}\n}\n\n/**\n * Internal logger instance\n * @internal\n */\nlet internalLogger: Logger = new NoOpLogger();\n\n/**\n * Get the current logger instance\n *\n * @returns The current logger instance\n */\nexport function getLogger(): Logger {\n\treturn internalLogger;\n}\n\n/**\n * Set a custom logger instance\n *\n * @public Use this to configure custom logging behavior.\n *\n * @param logger - Custom logger implementation or null to disable logging\n *\n * @example\n * ```typescript\n * import { setLogger } from '@selvajs/compute';\n *\n * // Enable console logging\n * setLogger(console);\n *\n * // Use a custom logger\n * setLogger({\n * debug: (msg, ...args) => myLogger.debug(msg, ...args),\n * info: (msg, ...args) => myLogger.info(msg, ...args),\n * warn: (msg, ...args) => myLogger.warn(msg, ...args),\n * error: (msg, ...args) => myLogger.error(msg, ...args)\n * });\n *\n * // Disable logging\n * setLogger(null);\n * ```\n */\nexport function setLogger(logger: Logger | Console | null): void {\n\tif (logger === null) {\n\t\tinternalLogger = new NoOpLogger();\n\t} else if ('debug' in logger && 'info' in logger && 'warn' in logger && 'error' in logger) {\n\t\tinternalLogger = logger as Logger;\n\t} else {\n\t\tinternalLogger = new ConsoleLogger();\n\t}\n}\n\n/**\n * Enable debug logging to console\n *\n * @public Convenience method to enable console logging.\n *\n * @example\n * ```typescript\n * import { enableDebugLogging } from '@selvajs/compute';\n *\n * enableDebugLogging();\n * ```\n */\nexport function enableDebugLogging(): void {\n\tsetLogger(new ConsoleLogger());\n}\n","import { RhinoComputeError, ErrorCodes } from '../errors';\nimport { getLogger } from '../utils/logger';\n\nimport type { ComputeConfig, RetryPolicy } from '../types';\nimport type {\n\tGrasshopperComputeConfig,\n\tGrasshopperComputeResponse,\n\tIoResponseSchema\n} from '@/features/grasshopper/types';\n\n/**\n * Valid endpoints for Rhino Compute (improved response type handling).\n */\nexport type Endpoint = 'grasshopper' | 'io' | string;\n\nexport type EndpointResponseMap = {\n\tgrasshopper: GrasshopperComputeResponse;\n\tio: IoResponseSchema;\n};\n\nexport type ComputeResponseFor<E extends string> = E extends keyof EndpointResponseMap\n\t? EndpointResponseMap[E]\n\t: unknown;\n\n// ============================================================================\n// Retry Policy\n// ============================================================================\n\nconst DEFAULT_RETRY: Required<RetryPolicy> = {\n\tattempts: 0,\n\tbaseDelayMs: 500,\n\tmaxDelayMs: 30_000,\n\tretryOn429: true\n};\n\nconst RETRYABLE_STATUS = new Set([502, 503, 504]);\n\nfunction resolveRetryPolicy(policy: RetryPolicy | undefined): Required<RetryPolicy> {\n\tif (!policy) return DEFAULT_RETRY;\n\treturn {\n\t\tattempts: policy.attempts ?? DEFAULT_RETRY.attempts,\n\t\tbaseDelayMs: policy.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs,\n\t\tmaxDelayMs: policy.maxDelayMs ?? DEFAULT_RETRY.maxDelayMs,\n\t\tretryOn429: policy.retryOn429 ?? DEFAULT_RETRY.retryOn429\n\t};\n}\n\n/**\n * Parse a Retry-After header value (seconds-int or HTTP-date) into ms.\n * Returns null if the header is missing or unparseable.\n */\nfunction parseRetryAfter(headerValue: string | null): number | null {\n\tif (!headerValue) return null;\n\tconst seconds = Number(headerValue);\n\tif (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n\tconst dateMs = Date.parse(headerValue);\n\tif (Number.isFinite(dateMs)) {\n\t\tconst delta = dateMs - Date.now();\n\t\treturn delta > 0 ? delta : 0;\n\t}\n\treturn null;\n}\n\nfunction backoffDelay(attempt: number, policy: Required<RetryPolicy>): number {\n\tconst exponential = policy.baseDelayMs * Math.pow(2, attempt);\n\tconst jitter = Math.random() * policy.baseDelayMs;\n\treturn Math.min(exponential + jitter, policy.maxDelayMs);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(new DOMException('Aborted', 'AbortError'));\n\t\t\treturn;\n\t\t}\n\t\tconst id = setTimeout(() => {\n\t\t\tsignal?.removeEventListener('abort', onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(id);\n\t\t\treject(new DOMException('Aborted', 'AbortError'));\n\t\t};\n\t\tsignal?.addEventListener('abort', onAbort, { once: true });\n\t});\n}\n\n// ============================================================================\n// Error Handling\n// ============================================================================\n\nfunction throwHttpError(\n\tresponse: Response,\n\tfullUrl: string,\n\trequestId: string,\n\trequestSize: number,\n\tserverUrl: string,\n\terrorBody: string\n): never {\n\tconst { status, statusText } = response;\n\tconst context = { url: fullUrl, requestId, method: 'POST', requestSize, serverUrl };\n\n\tconst bodyHint = errorBody ? ` — ${errorBody.slice(0, 200)}` : '';\n\tconst errorMap: Record<number, { message: string; code: string }> = {\n\t\t401: {\n\t\t\tmessage: `HTTP ${status}: ${statusText}${bodyHint}`,\n\t\t\tcode: ErrorCodes.AUTH_ERROR\n\t\t},\n\t\t403: {\n\t\t\tmessage: `HTTP ${status}: ${statusText}${bodyHint}`,\n\t\t\tcode: ErrorCodes.AUTH_ERROR\n\t\t},\n\t\t404: { message: `Endpoint not found: ${fullUrl}`, code: ErrorCodes.NETWORK_ERROR },\n\t\t413: {\n\t\t\tmessage: `Request too large: ${(requestSize / 1024).toFixed(2)}KB`,\n\t\t\tcode: ErrorCodes.VALIDATION_ERROR\n\t\t},\n\t\t429: { message: 'Rate limit exceeded', code: ErrorCodes.NETWORK_ERROR },\n\t\t500: {\n\t\t\tmessage: `Server error: ${errorBody || statusText}`,\n\t\t\tcode: ErrorCodes.COMPUTATION_ERROR\n\t\t},\n\t\t502: { message: `Service unavailable: ${statusText}`, code: ErrorCodes.NETWORK_ERROR },\n\t\t503: { message: `Service unavailable: ${statusText}`, code: ErrorCodes.NETWORK_ERROR },\n\t\t504: { message: `Service unavailable: ${statusText}`, code: ErrorCodes.NETWORK_ERROR }\n\t};\n\n\tconst error = errorMap[status] || {\n\t\tmessage: `HTTP ${status}: ${statusText}`,\n\t\tcode: ErrorCodes.UNKNOWN_ERROR\n\t};\n\n\tthrow new RhinoComputeError(error.message, error.code, { statusCode: status, context });\n}\n\n// ============================================================================\n// Request Helpers\n// ============================================================================\n\nfunction buildUrl(endpoint: string, serverUrl: string): string {\n\tconst base = serverUrl.replace(/\\/+$/, '');\n\tconst path = endpoint.replace(/^\\/+/, '');\n\treturn `${base}/${path}`;\n}\n\nfunction isLocalhost(serverUrl: string): boolean {\n\ttry {\n\t\tconst host = new URL(serverUrl).host;\n\t\treturn /^(localhost|127\\.0\\.0\\.1|::1)(:\\d+)?$/i.test(host);\n\t} catch {\n\t\treturn /(localhost|127\\.0\\.0\\.1)/i.test(serverUrl);\n\t}\n}\n\nfunction buildHeaders(requestId: string, config: ComputeConfig): HeadersInit {\n\tconst headers: HeadersInit = {\n\t\t'X-Request-ID': requestId,\n\t\t'Content-Type': 'application/json',\n\t\t...(config.authToken && { Authorization: config.authToken }),\n\t\t...(config.apiKey && { RhinoComputeKey: config.apiKey })\n\t};\n\n\tif (!config.apiKey && !isLocalhost(config.serverUrl)) {\n\t\tgetLogger().warn(\n\t\t\t`⚠️ [Rhino Compute] Request [${requestId}] targets remote server (${config.serverUrl}) but no API key is configured. Requests may fail or be rate-limited.`\n\t\t);\n\t}\n\n\treturn headers;\n}\n\nfunction generateRequestId(): string {\n\treturn `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nfunction log(message: string, debug?: boolean): void {\n\tif (debug) getLogger().debug(message);\n}\n\n/**\n * Compose a caller-supplied AbortSignal with an optional timeout. Returns a\n * combined signal, or `undefined` if neither was given.\n *\n * Uses `AbortSignal.timeout` (not setTimeout) so the timer is not throttled\n * when the tab is hidden. Falls back to a manual timer for older runtimes.\n */\nfunction composeSignal(\n\tcallerSignal: AbortSignal | undefined,\n\ttimeoutMs: number | undefined\n): { signal: AbortSignal | undefined; cleanup: () => void } {\n\tconst signals: AbortSignal[] = [];\n\tlet cleanup = () => {};\n\n\tif (callerSignal) signals.push(callerSignal);\n\n\tif (timeoutMs && timeoutMs > 0) {\n\t\tif (typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function') {\n\t\t\tsignals.push(AbortSignal.timeout(timeoutMs));\n\t\t} else {\n\t\t\t// Fallback for runtimes without AbortSignal.timeout\n\t\t\tconst ctrl = new AbortController();\n\t\t\tconst id = setTimeout(() => ctrl.abort(), timeoutMs);\n\t\t\tcleanup = () => clearTimeout(id);\n\t\t\tsignals.push(ctrl.signal);\n\t\t}\n\t}\n\n\tif (signals.length === 0) return { signal: undefined, cleanup };\n\tif (signals.length === 1) return { signal: signals[0], cleanup };\n\n\tif (typeof AbortSignal !== 'undefined' && typeof (AbortSignal as any).any === 'function') {\n\t\treturn { signal: (AbortSignal as any).any(signals) as AbortSignal, cleanup };\n\t}\n\n\t// Manual composition fallback\n\tconst ctrl = new AbortController();\n\tconst onAbort = () => ctrl.abort();\n\tfor (const s of signals) {\n\t\tif (s.aborted) {\n\t\t\tctrl.abort();\n\t\t\tbreak;\n\t\t}\n\t\ts.addEventListener('abort', onAbort, { once: true });\n\t}\n\tconst prevCleanup = cleanup;\n\tcleanup = () => {\n\t\tprevCleanup();\n\t\tfor (const s of signals) s.removeEventListener('abort', onAbort);\n\t};\n\treturn { signal: ctrl.signal, cleanup };\n}\n\n// ============================================================================\n// Response Processing\n// ============================================================================\n\nasync function handleResponse(\n\tresponse: Response,\n\tfullUrl: string,\n\trequestId: string,\n\trequestSize: number,\n\tserverUrl: string,\n\tstartTime: number,\n\tdebug?: boolean\n): Promise<any> {\n\tconst responseTime = Math.round(performance.now() - startTime);\n\n\tif (!response.ok) {\n\t\t// Read body once and reuse\n\t\tlet errorBody = await response.text();\n\n\t\t// Enhanced logging for errors\n\t\tif (debug) {\n\t\t\tlog(\n\t\t\t\t`❌ Request [${requestId}] failed with HTTP ${response.status} in ${responseTime}ms`,\n\t\t\t\ttrue\n\t\t\t);\n\t\t\tlog(` URL: ${fullUrl}`, true);\n\t\t\tlog(` Status: ${response.status} ${response.statusText}`, true);\n\t\t\tif (errorBody) {\n\t\t\t\tlog(\n\t\t\t\t\t` Response body: ${errorBody.substring(0, 500)}${errorBody.length > 500 ? '...' : ''}`,\n\t\t\t\t\ttrue\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Check if it's a valid compute response with errors/warnings\n\t\tif (response.status === 500) {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(errorBody);\n\t\t\t\t// If it has values, it's a partial success with errors\n\t\t\t\tif (parsed?.values && (parsed.errors || parsed.warnings)) {\n\t\t\t\t\tif (debug) {\n\t\t\t\t\t\tlog(\n\t\t\t\t\t\t\t`⚠️ Request [${requestId}] completed with Grasshopper errors in ${responseTime}ms`,\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (parsed.errors?.length > 0) {\n\t\t\t\t\t\t\tlog(` Errors: ${JSON.stringify(parsed.errors, null, 2)}`, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (parsed.warnings?.length > 0) {\n\t\t\t\t\t\t\tlog(` Warnings: ${JSON.stringify(parsed.warnings, null, 2)}`, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\n\t\t\t\t// If it's a raw exception from the server (like ArgumentException), include it in the error message\n\t\t\t\tif (parsed?.Message) {\n\t\t\t\t\terrorBody = `${parsed.ExceptionType ? parsed.ExceptionType + ': ' : ''}${parsed.Message}\\n${parsed.StackTrace || ''}`;\n\t\t\t\t} else if (parsed?.error) {\n\t\t\t\t\terrorBody =\n\t\t\t\t\t\ttypeof parsed.error === 'string' ? parsed.error : JSON.stringify(parsed.error, null, 2);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tif (debug) {\n\t\t\t\t\tlog(` Failed to parse error body as JSON: ${e}`, true);\n\t\t\t\t}\n\t\t\t\t// Not valid JSON, proceed with HTTP error\n\t\t\t}\n\t\t}\n\n\t\tthrowHttpError(response, fullUrl, requestId, requestSize, serverUrl, errorBody);\n\t}\n\n\tlog(`✅ Request [${requestId}] completed in ${responseTime}ms`, debug);\n\n\ttry {\n\t\treturn await response.json();\n\t} catch (error) {\n\t\tthrow new RhinoComputeError('Failed to parse JSON response', ErrorCodes.NETWORK_ERROR, {\n\t\t\tstatusCode: response.status,\n\t\t\tcontext: {\n\t\t\t\turl: fullUrl,\n\t\t\t\trequestId\n\t\t\t},\n\t\t\toriginalError: error instanceof Error ? error : new Error(String(error))\n\t\t});\n\t}\n}\n\n// ============================================================================\n// Single attempt\n// ============================================================================\n\ninterface AttemptContext {\n\tendpoint: string;\n\tbody: string;\n\trequestSize: number;\n\tfullUrl: string;\n\trequestId: string;\n\theaders: HeadersInit;\n\tconfig: ComputeConfig | GrasshopperComputeConfig;\n}\n\ninterface AttemptResult {\n\tok: true;\n\tvalue: any;\n}\n\ninterface AttemptRetry {\n\tok: false;\n\tretry: true;\n\tdelayMs: number;\n\tcause: RhinoComputeError;\n}\n\ninterface AttemptFatal {\n\tok: false;\n\tretry: false;\n\tcause: RhinoComputeError;\n}\n\nasync function attemptFetch(\n\tctx: AttemptContext,\n\tretryPolicy: Required<RetryPolicy>,\n\tattempt: number,\n\ttotalAttempts: number\n): Promise<AttemptResult | AttemptRetry | AttemptFatal> {\n\tconst { signal, cleanup } = composeSignal(ctx.config.signal, ctx.config.timeoutMs);\n\tconst startTime = performance.now();\n\n\ttry {\n\t\tconst response = await fetch(ctx.fullUrl, {\n\t\t\tmethod: 'POST',\n\t\t\tbody: ctx.body,\n\t\t\theaders: ctx.headers,\n\t\t\tsignal\n\t\t});\n\n\t\t// 429 with Retry-After or retryable 5xx → maybe retry\n\t\tconst isRetryableStatus =\n\t\t\tRETRYABLE_STATUS.has(response.status) ||\n\t\t\t(retryPolicy.retryOn429 && response.status === 429);\n\n\t\tif (isRetryableStatus && attempt < totalAttempts - 1) {\n\t\t\tconst retryAfterMs = parseRetryAfter(response.headers.get('Retry-After'));\n\t\t\tconst delayMs = retryAfterMs ?? backoffDelay(attempt, retryPolicy);\n\t\t\t// Drain the body so the connection can be reused\n\t\t\tawait response.text().catch(() => {});\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tretry: true,\n\t\t\t\tdelayMs,\n\t\t\t\tcause: new RhinoComputeError(\n\t\t\t\t\t`HTTP ${response.status} ${response.statusText} (will retry)`,\n\t\t\t\t\tErrorCodes.NETWORK_ERROR,\n\t\t\t\t\t{ statusCode: response.status, context: { requestId: ctx.requestId } }\n\t\t\t\t)\n\t\t\t};\n\t\t}\n\n\t\tconst value = await handleResponse(\n\t\t\tresponse,\n\t\t\tctx.fullUrl,\n\t\t\tctx.requestId,\n\t\t\tctx.requestSize,\n\t\t\tctx.config.serverUrl,\n\t\t\tstartTime,\n\t\t\tctx.config.debug\n\t\t);\n\t\treturn { ok: true, value };\n\t} catch (error) {\n\t\t// Caller-aborted vs timeout-aborted distinction\n\t\tif (error instanceof Error && (error.name === 'AbortError' || error.name === 'TimeoutError')) {\n\t\t\tconst callerAborted = ctx.config.signal?.aborted === true;\n\n\t\t\tif (callerAborted) {\n\t\t\t\t// Caller cancellation is never retried — propagate immediately\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tretry: false,\n\t\t\t\t\tcause: new RhinoComputeError('Request aborted by caller', ErrorCodes.UNKNOWN_ERROR, {\n\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\tendpoint: ctx.endpoint,\n\t\t\t\t\t\t\trequestId: ctx.requestId,\n\t\t\t\t\t\t\trequestSize: ctx.requestSize\n\t\t\t\t\t\t},\n\t\t\t\t\t\toriginalError: error\n\t\t\t\t\t})\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Timeout — retryable up to attempts limit\n\t\t\tconst fatal = new RhinoComputeError(\n\t\t\t\t`Request timed out after ${ctx.config.timeoutMs}ms`,\n\t\t\t\tErrorCodes.TIMEOUT_ERROR,\n\t\t\t\t{\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\tserverUrl: ctx.config.serverUrl,\n\t\t\t\t\t\ttimeoutMs: ctx.config.timeoutMs,\n\t\t\t\t\t\turl: ctx.fullUrl,\n\t\t\t\t\t\trequestId: ctx.requestId,\n\t\t\t\t\t\tendpoint: ctx.endpoint,\n\t\t\t\t\t\trequestSize: ctx.requestSize\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t\tif (attempt < totalAttempts - 1) {\n\t\t\t\treturn { ok: false, retry: true, delayMs: backoffDelay(attempt, retryPolicy), cause: fatal };\n\t\t\t}\n\t\t\treturn { ok: false, retry: false, cause: fatal };\n\t\t}\n\n\t\t// Network error (TypeError) — retryable\n\t\tif (error instanceof TypeError) {\n\t\t\tconst fatal = new RhinoComputeError(\n\t\t\t\t`Network error: ${error.message}`,\n\t\t\t\tErrorCodes.NETWORK_ERROR,\n\t\t\t\t{\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\tserverUrl: ctx.config.serverUrl,\n\t\t\t\t\t\turl: ctx.fullUrl,\n\t\t\t\t\t\trequestId: ctx.requestId,\n\t\t\t\t\t\tendpoint: ctx.endpoint,\n\t\t\t\t\t\trequestSize: ctx.requestSize\n\t\t\t\t\t},\n\t\t\t\t\toriginalError: error\n\t\t\t\t}\n\t\t\t);\n\t\t\tif (attempt < totalAttempts - 1) {\n\t\t\t\treturn { ok: false, retry: true, delayMs: backoffDelay(attempt, retryPolicy), cause: fatal };\n\t\t\t}\n\t\t\treturn { ok: false, retry: false, cause: fatal };\n\t\t}\n\n\t\t// RhinoComputeError thrown from handleResponse — already has full context.\n\t\t// Retryable only if it carries a retryable status code.\n\t\tif (error instanceof RhinoComputeError) {\n\t\t\tconst status = error.statusCode;\n\t\t\tconst retryable =\n\t\t\t\tstatus !== undefined &&\n\t\t\t\t(RETRYABLE_STATUS.has(status) || (retryPolicy.retryOn429 && status === 429));\n\t\t\tif (retryable && attempt < totalAttempts - 1) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tretry: true,\n\t\t\t\t\tdelayMs: backoffDelay(attempt, retryPolicy),\n\t\t\t\t\tcause: error\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { ok: false, retry: false, cause: error };\n\t\t}\n\n\t\t// Unknown — wrap and don't retry\n\t\treturn {\n\t\t\tok: false,\n\t\t\tretry: false,\n\t\t\tcause: new RhinoComputeError(\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\tErrorCodes.UNKNOWN_ERROR,\n\t\t\t\t{\n\t\t\t\t\tcontext: { endpoint: ctx.endpoint, requestId: ctx.requestId },\n\t\t\t\t\toriginalError: error instanceof Error ? error : new Error(String(error))\n\t\t\t\t}\n\t\t\t)\n\t\t};\n\t} finally {\n\t\tcleanup();\n\t}\n}\n\n// ============================================================================\n// Main Function\n// ============================================================================\n\n/**\n * Generic Rhino Compute fetch function.\n * Sends a POST request to any Compute endpoint with pre-prepared arguments.\n *\n * Use this for advanced, low-level control over compute requests. For most use cases, prefer higher-level APIs.\n *\n * @typeParam E - The endpoint name (e.g., 'grasshopper', 'io'). Determines the response type for better type safety.\n * @param endpoint - The Compute API endpoint (e.g., 'grasshopper', 'io', 'mesh').\n * @param args - Pre-prepared arguments for the request body.\n * @param config - Compute configuration (server URL, API key, timeout, debug, retry, signal).\n * @returns The parsed JSON response from the server, typed according to the endpoint.\n *\n * @example\n * // Basic usage for the Grasshopper endpoint:\n * const response = await fetchRhinoCompute(\n * 'grasshopper',\n * { ... },\n * {\n * serverUrl: 'https://my-server.com',\n * debug: true,\n * timeoutMs: 30_000,\n * retry: { attempts: 2 },\n * signal: controller.signal,\n * }\n * );\n */\nexport async function fetchRhinoCompute<E extends Endpoint>(\n\tendpoint: E,\n\targs: Record<string, any>,\n\tconfig: ComputeConfig | GrasshopperComputeConfig\n): Promise<ComputeResponseFor<E>> {\n\tconst requestId = generateRequestId();\n\tconst body = JSON.stringify(args);\n\tconst requestSize = body.length;\n\tconst fullUrl = buildUrl(endpoint, config.serverUrl);\n\tconst headers = buildHeaders(requestId, config);\n\tconst retryPolicy = resolveRetryPolicy(config.retry);\n\tconst totalAttempts = retryPolicy.attempts + 1;\n\n\tif (config.debug) {\n\t\tconst sizeKb = (requestSize / 1024).toFixed(2);\n\t\tconst emoji = requestSize > 100000 ? '⚠️' : '🚀';\n\t\tlog(`${emoji} Starting compute request [${requestId}]: ${endpoint} (${sizeKb}KB)`, true);\n\t}\n\n\tconst ctx: AttemptContext = {\n\t\tendpoint,\n\t\tbody,\n\t\trequestSize,\n\t\tfullUrl,\n\t\trequestId,\n\t\theaders,\n\t\tconfig\n\t};\n\n\tlet lastError: RhinoComputeError | null = null;\n\n\tfor (let attempt = 0; attempt < totalAttempts; attempt++) {\n\t\tconst result = await attemptFetch(ctx, retryPolicy, attempt, totalAttempts);\n\n\t\tif (result.ok) return result.value as ComputeResponseFor<E>;\n\n\t\tif (!result.retry) throw result.cause;\n\n\t\tlastError = result.cause;\n\t\tif (config.debug) {\n\t\t\tlog(\n\t\t\t\t`🔁 Request [${requestId}] retrying after ${result.delayMs}ms (attempt ${attempt + 2}/${totalAttempts}): ${result.cause.message}`,\n\t\t\t\ttrue\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tawait sleep(result.delayMs, config.signal);\n\t\t} catch {\n\t\t\t// Caller cancelled during backoff\n\t\t\tthrow new RhinoComputeError('Request aborted by caller', ErrorCodes.UNKNOWN_ERROR, {\n\t\t\t\tcontext: { endpoint, requestId, requestSize },\n\t\t\t\toriginalError: lastError\n\t\t\t});\n\t\t}\n\t}\n\n\t// Exhausted retries — throw the last seen error\n\tthrow (\n\t\tlastError ??\n\t\tnew RhinoComputeError('Unknown error after retries', ErrorCodes.UNKNOWN_ERROR, {\n\t\t\tcontext: { endpoint, requestId, requestSize }\n\t\t})\n\t);\n}\n","import { RhinoComputeError, ErrorCodes } from '../errors';\nimport { getLogger } from '../utils/logger';\n\n/**\n * ComputeServerStats provides methods to query Rhino Compute server statistics.\n *\n * @public Use this for server health monitoring and statistics.\n *\n * @example\n * ```typescript\n * const stats = new ComputeServerStats('http://localhost:6500', 'your-api-key');\n *\n * try {\n * const isOnline = await stats.isServerOnline();\n * const children = await stats.getActiveChildren();\n * const version = await stats.getVersion();\n *\n * // Or get everything at once\n * const allStats = await stats.getServerStats();\n * } finally {\n * await stats.dispose(); // Clean up resources\n * }\n * ```\n */\nexport default class ComputeServerStats {\n\tprivate readonly serverUrl: string;\n\tprivate readonly apiKey?: string;\n\tprivate disposed = false;\n\tprivate activeMonitors: Set<() => void> = new Set();\n\tprivate activeTimeouts: Set<ReturnType<typeof setTimeout>> = new Set();\n\n\t/**\n\t * @param serverUrl - Base URL of the Rhino Compute server with http:// or https:// scheme (e.g., 'http://localhost:6500')\n\t * @param apiKey - Optional API key for authentication\n\t */\n\tconstructor(serverUrl: string, apiKey?: string) {\n\t\tif (!serverUrl?.trim()) {\n\t\t\tthrow new RhinoComputeError('serverUrl is required', ErrorCodes.INVALID_CONFIG, {\n\t\t\t\tcontext: { serverUrl }\n\t\t\t});\n\t\t}\n\n\t\t// Validate URL has http:// or https:// scheme\n\t\tif (!serverUrl.match(/^https?:\\/\\//)) {\n\t\t\tthrow new RhinoComputeError(\n\t\t\t\t`Invalid serverUrl: \"${serverUrl}\". Must start with \"http://\" or \"https://\". ` +\n\t\t\t\t\t`For example: \"http://localhost:5000\" or \"https://example.com\"`,\n\t\t\t\tErrorCodes.INVALID_CONFIG,\n\t\t\t\t{ context: { serverUrl } }\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tnew URL(serverUrl);\n\t\t} catch (err) {\n\t\t\tthrow new RhinoComputeError(\n\t\t\t\t`Invalid serverUrl: \"${serverUrl}\". Must be a valid URL. ` +\n\t\t\t\t\t`Received error: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t\tErrorCodes.INVALID_CONFIG,\n\t\t\t\t{\n\t\t\t\t\tcontext: { serverUrl },\n\t\t\t\t\toriginalError: err instanceof Error ? err : undefined\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tthis.apiKey = apiKey;\n\t\tthis.serverUrl = serverUrl.replace(/\\/+$/, '');\n\t}\n\n\t/**\n\t * Build request headers with optional API key.\n\t */\n\tprivate buildHeaders(): HeadersInit {\n\t\tconst headers: HeadersInit = {\n\t\t\t'Content-Type': 'application/json'\n\t\t};\n\n\t\tif (this.apiKey) {\n\t\t\theaders['RhinoComputeKey'] = this.apiKey;\n\t\t}\n\n\t\treturn headers;\n\t}\n\n\t/**\n\t * Check if the server is online.\n\t */\n\tpublic async isServerOnline(): Promise<boolean> {\n\t\tthis.ensureNotDisposed();\n\n\t\tconst url = `${this.serverUrl}/healthcheck`;\n\t\tconst init: RequestInit = { headers: this.buildHeaders(), method: 'GET' };\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, init);\n\n\t\t\treturn response.ok;\n\t\t} catch (err) {\n\t\t\tgetLogger().debug('[ComputeServerStats] Fetch error:', err);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Get the number of active child processes on the server.\n\t *\n\t * @returns Number of active children, or null if unavailable\n\t */\n\tpublic async getActiveChildren(): Promise<number | null> {\n\t\tthis.ensureNotDisposed();\n\n\t\ttry {\n\t\t\tconst response = await fetch(`${this.serverUrl}/activechildren`, {\n\t\t\t\theaders: this.buildHeaders()\n\t\t\t});\n\t\t\tif (!response.ok) {\n\t\t\t\tgetLogger().warn('[ComputeServerStats] Failed to fetch active children:', response.status);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst text = await response.text();\n\t\t\tconst count = parseInt(text.trim(), 10);\n\n\t\t\tif (isNaN(count)) {\n\t\t\t\tgetLogger().warn('[ComputeServerStats] Invalid active children response:', text);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn count;\n\t\t} catch (err) {\n\t\t\tgetLogger().warn('[ComputeServerStats] Error fetching active children:', err);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the server version information.\n\t *\n\t * @returns Version object with rhino, compute, and git_sha, or null if unavailable\n\t */\n\tpublic async getVersion(): Promise<{\n\t\trhino: string;\n\t\tcompute: string;\n\t\tgit_sha: string | null;\n\t} | null> {\n\t\tthis.ensureNotDisposed();\n\n\t\ttry {\n\t\t\tconst response = await fetch(`${this.serverUrl}/version`, {\n\t\t\t\theaders: this.buildHeaders()\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tgetLogger().warn('[ComputeServerStats] Failed to fetch version:', response.status);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst json = await response.json();\n\t\t\t\treturn {\n\t\t\t\t\trhino: json.rhino ?? '',\n\t\t\t\t\tcompute: json.compute ?? '',\n\t\t\t\t\tgit_sha: json.git_sha ?? null\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// Fallback: parse as plain text\n\t\t\t\tconst text = await response.text();\n\t\t\t\treturn { rhino: text, compute: '', git_sha: null };\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tgetLogger().warn('[ComputeServerStats] Error fetching version:', err);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get comprehensive server statistics.\n\t * Fetches all available server information in parallel.\n\t *\n\t * @returns Object containing server status and available stats\n\t */\n\tpublic async getServerStats(): Promise<{\n\t\tisOnline: boolean;\n\t\tversion?: { rhino: string; compute: string; git_sha: string | null };\n\t\tactiveChildren?: number;\n\t}> {\n\t\tthis.ensureNotDisposed();\n\n\t\tconst isOnline = await this.isServerOnline();\n\n\t\tif (!isOnline) {\n\t\t\treturn { isOnline: false };\n\t\t}\n\n\t\tconst [version, activeChildren] = await Promise.all([\n\t\t\tthis.getVersion(),\n\t\t\tthis.getActiveChildren()\n\t\t]);\n\n\t\treturn {\n\t\t\tisOnline: true,\n\t\t\t...(version && { version }),\n\t\t\t...(activeChildren !== null && { activeChildren })\n\t\t};\n\t}\n\n\t/**\n\t * Continuously monitor server stats at specified interval.\n\t *\n\t * @param callback - Function called with stats on each interval\n\t * @param intervalMs - Milliseconds between checks (default: 5000)\n\t * @returns Function to stop monitoring\n\t *\n\t * @example\n\t * ```typescript\n\t * const stopMonitoring = stats.monitor((data) => {\n\t * console.log('Server stats:', data);\n\t * }, 3000);\n\t *\n\t * // Later...\n\t * stopMonitoring();\n\t * ```\n\t */\n\tpublic monitor(\n\t\tcallback: (stats: Awaited<ReturnType<typeof this.getServerStats>>) => void,\n\t\tintervalMs: number = 5000\n\t): () => void {\n\t\tthis.ensureNotDisposed();\n\n\t\tlet active = true;\n\t\tlet currentTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n\t\tgetLogger().info(`🔄 Starting server stats monitoring every ${intervalMs}ms`);\n\n\t\tconst check = async () => {\n\t\t\t// Clear current timeout from tracking since it has fired\n\t\t\tif (currentTimeoutId !== null) {\n\t\t\t\tthis.activeTimeouts.delete(currentTimeoutId);\n\t\t\t\tcurrentTimeoutId = null;\n\t\t\t}\n\n\t\t\tif (!active || this.disposed) return;\n\n\t\t\ttry {\n\t\t\t\tconst _stats = await this.getServerStats();\n\n\t\t\t\t// Check again after async operation to prevent race condition\n\t\t\t\tif (!active || this.disposed) return;\n\n\t\t\t\ttry {\n\t\t\t\t\tcallback(_stats);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tgetLogger().error('[ComputeServerStats] Monitor callback threw:', err);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tgetLogger().error('[ComputeServerStats] Failed to fetch stats during monitor:', err);\n\t\t\t}\n\n\t\t\tif (active && !this.disposed) {\n\t\t\t\tcurrentTimeoutId = setTimeout(() => void check(), intervalMs);\n\t\t\t\tthis.activeTimeouts.add(currentTimeoutId);\n\t\t\t}\n\t\t};\n\n\t\tconst stopMonitoring = () => {\n\t\t\tactive = false;\n\n\t\t\t// Clear any pending timeout\n\t\t\tif (currentTimeoutId !== null) {\n\t\t\t\tclearTimeout(currentTimeoutId);\n\t\t\t\tthis.activeTimeouts.delete(currentTimeoutId);\n\t\t\t\tcurrentTimeoutId = null;\n\t\t\t}\n\n\t\t\tthis.activeMonitors.delete(stopMonitoring);\n\t\t};\n\n\t\tthis.activeMonitors.add(stopMonitoring);\n\n\t\t// Explicitly mark as fire-and-forget since we don't need to await the initial call\n\t\tvoid check();\n\n\t\treturn stopMonitoring;\n\t}\n\n\t/**\n\t * Disposes of all resources and stops all active monitors.\n\t * Call this when you're done using the stats instance.\n\t */\n\tpublic async dispose(): Promise<void> {\n\t\tif (this.disposed) return;\n\n\t\tthis.disposed = true;\n\n\t\t// Stop all active monitors (this will also clear their timeouts)\n\t\tfor (const stopMonitor of this.activeMonitors) {\n\t\t\tstopMonitor();\n\t\t}\n\t\tthis.activeMonitors.clear();\n\n\t\t// Clear any remaining timeouts (defensive cleanup)\n\t\tfor (const timeoutId of this.activeTimeouts) {\n\t\t\tclearTimeout(timeoutId);\n\t\t}\n\t\tthis.activeTimeouts.clear();\n\t}\n\n\t/**\n\t * Ensures the instance hasn't been disposed.\n\t */\n\tprivate ensureNotDisposed(): void {\n\t\tif (this.disposed) {\n\t\t\tthrow new RhinoComputeError(\n\t\t\t\t'ComputeServerStats has been disposed and cannot be used',\n\t\t\t\tErrorCodes.INVALID_STATE,\n\t\t\t\t{ context: { disposed: this.disposed } }\n\t\t\t);\n\t\t}\n\t}\n}\n","/**\n * Converts a string to camelCase.\n * @param str - The string to convert\n * @param options - Options object\n * - preserveSpaces: If true, spaces are preserved (default: false)\n */\nexport function toCamelCase(str: string, options: { preserveSpaces?: boolean } = {}): string {\n\tconst { preserveSpaces = false } = options;\n\tlet s = str.trim();\n\tif (!preserveSpaces) {\n\t\t// Remove spaces, dashes, and underscores, camelCase the next letter\n\t\ts = s\n\t\t\t.replace(/^[A-Z]/, (m) => m.toLowerCase())\n\t\t\t.replace(/[\\s-_]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''));\n\t\treturn s;\n\t} else {\n\t\t// Only camelCase after dashes/underscores, preserve spaces\n\t\ts =\n\t\t\ts.charAt(0).toLowerCase() +\n\t\t\ts.slice(1).replace(/[-_](.)/g, (_, c) => (c ? c.toUpperCase() : ''));\n\t\treturn s;\n\t}\n}\n\n/**\n * Recursively converts all object keys to camelCase.\n * @param obj - The object to process\n * @param options - Options object\n * - deep: If true, process deeply\n * - preserveSpaces: If true, spaces are preserved in keys\n * @returns The new object with camelCased keys\n * @internal\n */\nexport function camelcaseKeys(\n\tobj: unknown,\n\toptions: { deep?: boolean; preserveSpaces?: boolean } = {}\n): unknown {\n\tif (!obj || typeof obj !== 'object') {\n\t\treturn obj;\n\t}\n\n\tif (Array.isArray(obj)) {\n\t\treturn options.deep ? obj.map((item) => camelcaseKeys(item, options)) : obj;\n\t}\n\n\treturn Object.keys(obj).reduce(\n\t\t(result, key) => {\n\t\t\tconst camelKey = toCamelCase(key, { preserveSpaces: options.preserveSpaces });\n\t\t\tconst value = (obj as any)[key];\n\t\t\t(result as any)[camelKey] = options.deep ? camelcaseKeys(value, options) : value;\n\t\t\treturn result;\n\t\t},\n\t\t{} as Record<string, unknown>\n\t);\n}\n"],"mappings":"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","names":["ErrorCodes","RhinoComputeError","_RhinoComputeError","message","code","options","__publicField","inputName","reason","context","ErrorCodes","expectedType","defaultValue","availableValues","paramType","paramName","expectedStructure","NoOpLogger","ConsoleLogger","message","args","internalLogger","getLogger","setLogger","logger","enableDebugLogging","DEFAULT_RETRY","RETRYABLE_STATUS","resolveRetryPolicy","policy","parseRetryAfter","headerValue","seconds","dateMs","delta","backoffDelay","attempt","exponential","jitter","sleep","ms","signal","resolve","reject","id","onAbort","throwHttpError","response","fullUrl","requestId","requestSize","serverUrl","errorBody","status","statusText","context","bodyHint","error","ErrorCodes","RhinoComputeError","buildUrl","endpoint","base","path","isLocalhost","host","buildHeaders","config","headers","getLogger","generateRequestId","log","message","debug","composeSignal","callerSignal","timeoutMs","signals","cleanup","ctrl","s","prevCleanup","handleResponse","startTime","responseTime","parsed","e","attemptFetch","ctx","retryPolicy","totalAttempts","delayMs","fatal","fetchRhinoCompute","args","body","sizeKb","emoji","lastError","result","ComputeServerStats","serverUrl","apiKey","__publicField","RhinoComputeError","ErrorCodes","err","headers","url","init","getLogger","response","text","count","json","version","activeChildren","callback","intervalMs","active","currentTimeoutId","check","_stats","stopMonitoring","stopMonitor","timeoutId","toCamelCase","str","options","preserveSpaces","s","_","c","m","camelcaseKeys","obj","item","result","key","camelKey","value"]}
1
+ {"version":3,"sources":["../src/core/errors/error-codes.ts","../src/core/errors/base.ts","../src/core/utils/logger.ts","../src/core/compute-fetch/compute-fetch.ts","../src/core/server/compute-server-stats.ts","../src/core/utils/camel-case.ts"],"sourcesContent":["export const ErrorCodes = {\n\tNETWORK_ERROR: 'NETWORK_ERROR',\n\tAUTH_ERROR: 'AUTH_ERROR',\n\tVALIDATION_ERROR: 'VALIDATION_ERROR',\n\tCOMPUTATION_ERROR: 'COMPUTATION_ERROR',\n\tTIMEOUT_ERROR: 'TIMEOUT_ERROR',\n\tCORS_ERROR: 'CORS_ERROR',\n\tUNKNOWN_ERROR: 'UNKNOWN_ERROR',\n\tINVALID_STATE: 'INVALID_STATE',\n\tINVALID_INPUT: 'INVALID_INPUT',\n\tINVALID_CONFIG: 'INVALID_CONFIG',\n\tBROWSER_ONLY: 'BROWSER_ONLY',\n\tENVIRONMENT_ERROR: 'ENVIRONMENT_ERROR',\n\tENCODING_ERROR: 'ENCODING_ERROR'\n} as const;\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n","import { ErrorCodes } from './error-codes';\n\n/**\n * Simplified error for Rhino Compute operations\n *\n * @public Use this for error handling with error codes and context.\n */\nexport class RhinoComputeError extends Error {\n\tpublic readonly code: string;\n\tpublic readonly statusCode?: number;\n\tpublic readonly context?: Record<string, unknown>;\n\tpublic readonly originalError?: Error;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tcode: string = 'UNKNOWN_ERROR',\n\t\toptions?: { statusCode?: number; context?: Record<string, unknown>; originalError?: Error }\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'RhinoComputeError';\n\t\tthis.code = code;\n\t\tthis.statusCode = options?.statusCode;\n\t\tthis.context = options?.context;\n\t\tthis.originalError = options?.originalError;\n\n\t\t// Support error chaining (Node.js 16.9+, TypeScript 4.6+)\n\t\tif ('cause' in Error.prototype) {\n\t\t\tObject.defineProperty(this, 'cause', {\n\t\t\t\tvalue: options?.originalError,\n\t\t\t\tenumerable: true\n\t\t\t});\n\t\t}\n\t}\n\n\t// ============================================================================\n\t// Static Validation Error Helpers\n\t// ============================================================================\n\n\t/**\n\t * Create a generic validation error with custom reason\n\t */\n\tstatic validation(inputName: string, reason: string, context?: Record<string, unknown>) {\n\t\treturn new RhinoComputeError(`Input \"${inputName}\": ${reason}`, ErrorCodes.VALIDATION_ERROR, {\n\t\t\tcontext: { inputName, reason, ...context }\n\t\t});\n\t}\n\n\t/**\n\t * Create an error for missing/empty values\n\t */\n\tstatic missingValues(inputName: string, expectedType?: string, context?: Record<string, unknown>) {\n\t\treturn new RhinoComputeError(\n\t\t\t`Input \"${inputName}\" has no values defined${expectedType ? ` (expected ${expectedType})` : ''}`,\n\t\t\tErrorCodes.INVALID_INPUT,\n\t\t\t{ context: { inputName, expectedType, ...context } }\n\t\t);\n\t}\n\n\t/**\n\t * Create an error for invalid default value in value list\n\t */\n\tstatic invalidDefault(\n\t\tinputName: string,\n\t\tdefaultValue: unknown,\n\t\tavailableValues: unknown[],\n\t\tcontext?: Record<string, unknown>\n\t) {\n\t\treturn new RhinoComputeError(\n\t\t\t`ValueList input \"${inputName}\" default value \"${defaultValue}\" is not in available values`,\n\t\t\tErrorCodes.VALIDATION_ERROR,\n\t\t\t{ context: { inputName, defaultValue, availableValues, ...context } }\n\t\t);\n\t}\n\n\t/**\n\t * Create an error for unknown parameter type\n\t */\n\tstatic unknownParamType(paramType: string, paramName?: string, context?: Record<string, unknown>) {\n\t\treturn new RhinoComputeError(`Unknown paramType: ${paramType}`, ErrorCodes.VALIDATION_ERROR, {\n\t\t\tcontext: { receivedParamType: paramType, paramName, ...context }\n\t\t});\n\t}\n\n\t/**\n\t * Create an error for invalid input structure\n\t */\n\tstatic invalidStructure(\n\t\tinputName: string,\n\t\texpectedStructure: string,\n\t\tcontext?: Record<string, unknown>\n\t) {\n\t\treturn new RhinoComputeError(\n\t\t\t`Invalid input structure for \"${inputName}\" (expected ${expectedStructure})`,\n\t\t\tErrorCodes.INVALID_INPUT,\n\t\t\t{ context: { inputName, expectedStructure, ...context } }\n\t\t);\n\t}\n}\n","/**\n * Logger interface for structured logging\n *\n * @public Implement this interface to provide custom logging behavior.\n */\nexport interface Logger {\n\tdebug(message: string, ...args: unknown[]): void;\n\tinfo(message: string, ...args: unknown[]): void;\n\twarn(message: string, ...args: unknown[]): void;\n\terror(message: string, ...args: unknown[]): void;\n}\n\n/**\n * No-op logger implementation (default)\n * @internal\n */\nclass NoOpLogger implements Logger {\n\tdebug(): void {}\n\tinfo(): void {}\n\twarn(): void {}\n\terror(): void {}\n}\n\n/**\n * Console logger implementation\n * @internal\n */\nclass ConsoleLogger implements Logger {\n\tdebug(message: string, ...args: unknown[]): void {\n\t\tconsole.debug(message, ...args);\n\t}\n\n\tinfo(message: string, ...args: unknown[]): void {\n\t\tconsole.info(message, ...args);\n\t}\n\n\twarn(message: string, ...args: unknown[]): void {\n\t\tconsole.warn(message, ...args);\n\t}\n\n\terror(message: string, ...args: unknown[]): void {\n\t\tconsole.error(message, ...args);\n\t}\n}\n\n/**\n * Internal logger instance\n * @internal\n */\nlet internalLogger: Logger = new NoOpLogger();\n\n/**\n * Get the current logger instance\n *\n * @returns The current logger instance\n */\nexport function getLogger(): Logger {\n\treturn internalLogger;\n}\n\n/**\n * Set a custom logger instance\n *\n * @public Use this to configure custom logging behavior.\n *\n * @param logger - Custom logger implementation or null to disable logging\n *\n * @example\n * ```typescript\n * import { setLogger } from '@selvajs/compute';\n *\n * // Enable console logging\n * setLogger(console);\n *\n * // Use a custom logger\n * setLogger({\n * debug: (msg, ...args) => myLogger.debug(msg, ...args),\n * info: (msg, ...args) => myLogger.info(msg, ...args),\n * warn: (msg, ...args) => myLogger.warn(msg, ...args),\n * error: (msg, ...args) => myLogger.error(msg, ...args)\n * });\n *\n * // Disable logging\n * setLogger(null);\n * ```\n */\nexport function setLogger(logger: Logger | Console | null): void {\n\tif (logger === null) {\n\t\tinternalLogger = new NoOpLogger();\n\t} else if ('debug' in logger && 'info' in logger && 'warn' in logger && 'error' in logger) {\n\t\tinternalLogger = logger as Logger;\n\t} else {\n\t\tinternalLogger = new ConsoleLogger();\n\t}\n}\n\n/**\n * Enable debug logging to console\n *\n * @public Convenience method to enable console logging.\n *\n * @example\n * ```typescript\n * import { enableDebugLogging } from '@selvajs/compute';\n *\n * enableDebugLogging();\n * ```\n */\nexport function enableDebugLogging(): void {\n\tsetLogger(new ConsoleLogger());\n}\n","import { RhinoComputeError, ErrorCodes } from '../errors';\nimport { getLogger } from '../utils/logger';\n\nimport type { ComputeConfig, RetryPolicy } from '../types';\nimport type {\n\tGrasshopperComputeConfig,\n\tGrasshopperComputeResponse,\n\tIoResponseSchema\n} from '@/features/grasshopper/types';\n\n/**\n * Valid endpoints for Rhino Compute (improved response type handling).\n */\nexport type Endpoint = 'grasshopper' | 'io' | string;\n\nexport type EndpointResponseMap = {\n\tgrasshopper: GrasshopperComputeResponse;\n\tio: IoResponseSchema;\n};\n\nexport type ComputeResponseFor<E extends string> = E extends keyof EndpointResponseMap\n\t? EndpointResponseMap[E]\n\t: unknown;\n\n// ============================================================================\n// Retry Policy\n// ============================================================================\n\nconst DEFAULT_RETRY: Required<RetryPolicy> = {\n\tattempts: 0,\n\tbaseDelayMs: 500,\n\tmaxDelayMs: 30_000,\n\tretryOn429: true\n};\n\nconst RETRYABLE_STATUS = new Set([502, 503, 504]);\n\nfunction resolveRetryPolicy(policy: RetryPolicy | undefined): Required<RetryPolicy> {\n\tif (!policy) return DEFAULT_RETRY;\n\treturn {\n\t\tattempts: policy.attempts ?? DEFAULT_RETRY.attempts,\n\t\tbaseDelayMs: policy.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs,\n\t\tmaxDelayMs: policy.maxDelayMs ?? DEFAULT_RETRY.maxDelayMs,\n\t\tretryOn429: policy.retryOn429 ?? DEFAULT_RETRY.retryOn429\n\t};\n}\n\n/**\n * Parse a Retry-After header value (seconds-int or HTTP-date) into ms.\n * Returns null if the header is missing or unparseable.\n */\nfunction parseRetryAfter(headerValue: string | null): number | null {\n\tif (!headerValue) return null;\n\tconst seconds = Number(headerValue);\n\tif (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n\tconst dateMs = Date.parse(headerValue);\n\tif (Number.isFinite(dateMs)) {\n\t\tconst delta = dateMs - Date.now();\n\t\treturn delta > 0 ? delta : 0;\n\t}\n\treturn null;\n}\n\nfunction backoffDelay(attempt: number, policy: Required<RetryPolicy>): number {\n\tconst exponential = policy.baseDelayMs * Math.pow(2, attempt);\n\tconst jitter = Math.random() * policy.baseDelayMs;\n\treturn Math.min(exponential + jitter, policy.maxDelayMs);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(new DOMException('Aborted', 'AbortError'));\n\t\t\treturn;\n\t\t}\n\t\tconst id = setTimeout(() => {\n\t\t\tsignal?.removeEventListener('abort', onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(id);\n\t\t\treject(new DOMException('Aborted', 'AbortError'));\n\t\t};\n\t\tsignal?.addEventListener('abort', onAbort, { once: true });\n\t});\n}\n\n// ============================================================================\n// Error Handling\n// ============================================================================\n\nfunction throwHttpError(\n\tresponse: Response,\n\tfullUrl: string,\n\trequestId: string,\n\trequestSize: number,\n\tserverUrl: string,\n\terrorBody: string\n): never {\n\tconst { status, statusText } = response;\n\tconst context = { url: fullUrl, requestId, method: 'POST', requestSize, serverUrl };\n\n\tconst bodyHint = errorBody ? ` — ${errorBody.slice(0, 200)}` : '';\n\tconst errorMap: Record<number, { message: string; code: string }> = {\n\t\t401: {\n\t\t\tmessage: `HTTP ${status}: ${statusText}${bodyHint}`,\n\t\t\tcode: ErrorCodes.AUTH_ERROR\n\t\t},\n\t\t403: {\n\t\t\tmessage: `HTTP ${status}: ${statusText}${bodyHint}`,\n\t\t\tcode: ErrorCodes.AUTH_ERROR\n\t\t},\n\t\t404: { message: `Endpoint not found: ${fullUrl}`, code: ErrorCodes.NETWORK_ERROR },\n\t\t413: {\n\t\t\tmessage: `Request too large: ${(requestSize / 1024).toFixed(2)}KB`,\n\t\t\tcode: ErrorCodes.VALIDATION_ERROR\n\t\t},\n\t\t429: { message: 'Rate limit exceeded', code: ErrorCodes.NETWORK_ERROR },\n\t\t500: {\n\t\t\tmessage: `Server error: ${errorBody || statusText}`,\n\t\t\tcode: ErrorCodes.COMPUTATION_ERROR\n\t\t},\n\t\t502: { message: `Service unavailable: ${statusText}`, code: ErrorCodes.NETWORK_ERROR },\n\t\t503: { message: `Service unavailable: ${statusText}`, code: ErrorCodes.NETWORK_ERROR },\n\t\t504: { message: `Service unavailable: ${statusText}`, code: ErrorCodes.NETWORK_ERROR }\n\t};\n\n\tconst error = errorMap[status] || {\n\t\tmessage: `HTTP ${status}: ${statusText}`,\n\t\tcode: ErrorCodes.UNKNOWN_ERROR\n\t};\n\n\tthrow new RhinoComputeError(error.message, error.code, { statusCode: status, context });\n}\n\n// ============================================================================\n// Request Helpers\n// ============================================================================\n\nfunction buildUrl(endpoint: string, serverUrl: string): string {\n\tconst base = serverUrl.replace(/\\/+$/, '');\n\tconst path = endpoint.replace(/^\\/+/, '');\n\treturn `${base}/${path}`;\n}\n\nfunction isLocalhost(serverUrl: string): boolean {\n\ttry {\n\t\tconst host = new URL(serverUrl).host;\n\t\treturn /^(localhost|127\\.0\\.0\\.1|::1)(:\\d+)?$/i.test(host);\n\t} catch {\n\t\treturn /(localhost|127\\.0\\.0\\.1)/i.test(serverUrl);\n\t}\n}\n\nfunction buildHeaders(requestId: string, config: ComputeConfig): HeadersInit {\n\tconst headers: HeadersInit = {\n\t\t'X-Request-ID': requestId,\n\t\t'Content-Type': 'application/json',\n\t\t...(config.authToken && { Authorization: config.authToken }),\n\t\t...(config.apiKey && { RhinoComputeKey: config.apiKey })\n\t};\n\n\tif (!config.apiKey && !isLocalhost(config.serverUrl)) {\n\t\tgetLogger().warn(\n\t\t\t`⚠️ [Rhino Compute] Request [${requestId}] targets remote server (${config.serverUrl}) but no API key is configured. Requests may fail or be rate-limited.`\n\t\t);\n\t}\n\n\treturn headers;\n}\n\nfunction generateRequestId(): string {\n\treturn `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nfunction log(message: string, debug?: boolean): void {\n\tif (debug) getLogger().debug(message);\n}\n\n/**\n * Compose a caller-supplied AbortSignal with an optional timeout. Returns a\n * combined signal, or `undefined` if neither was given.\n *\n * Uses `AbortSignal.timeout` (not setTimeout) so the timer is not throttled\n * when the tab is hidden. Falls back to a manual timer for older runtimes.\n */\nfunction composeSignal(\n\tcallerSignal: AbortSignal | undefined,\n\ttimeoutMs: number | undefined\n): { signal: AbortSignal | undefined; cleanup: () => void } {\n\tconst signals: AbortSignal[] = [];\n\tlet cleanup = () => {};\n\n\tif (callerSignal) signals.push(callerSignal);\n\n\tif (timeoutMs && timeoutMs > 0) {\n\t\tif (typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function') {\n\t\t\tsignals.push(AbortSignal.timeout(timeoutMs));\n\t\t} else {\n\t\t\t// Fallback for runtimes without AbortSignal.timeout\n\t\t\tconst ctrl = new AbortController();\n\t\t\tconst id = setTimeout(() => ctrl.abort(), timeoutMs);\n\t\t\tcleanup = () => clearTimeout(id);\n\t\t\tsignals.push(ctrl.signal);\n\t\t}\n\t}\n\n\tif (signals.length === 0) return { signal: undefined, cleanup };\n\tif (signals.length === 1) return { signal: signals[0], cleanup };\n\n\tif (typeof AbortSignal !== 'undefined' && typeof (AbortSignal as any).any === 'function') {\n\t\treturn { signal: (AbortSignal as any).any(signals) as AbortSignal, cleanup };\n\t}\n\n\t// Manual composition fallback\n\tconst ctrl = new AbortController();\n\tconst onAbort = () => ctrl.abort();\n\tfor (const s of signals) {\n\t\tif (s.aborted) {\n\t\t\tctrl.abort();\n\t\t\tbreak;\n\t\t}\n\t\ts.addEventListener('abort', onAbort, { once: true });\n\t}\n\tconst prevCleanup = cleanup;\n\tcleanup = () => {\n\t\tprevCleanup();\n\t\tfor (const s of signals) s.removeEventListener('abort', onAbort);\n\t};\n\treturn { signal: ctrl.signal, cleanup };\n}\n\n// ============================================================================\n// Response Processing\n// ============================================================================\n\nasync function handleResponse(\n\tresponse: Response,\n\tfullUrl: string,\n\trequestId: string,\n\trequestSize: number,\n\tserverUrl: string,\n\tstartTime: number,\n\tdebug?: boolean\n): Promise<any> {\n\tconst responseTime = Math.round(performance.now() - startTime);\n\n\tif (!response.ok) {\n\t\t// Read body once and reuse\n\t\tlet errorBody = await response.text();\n\n\t\t// Enhanced logging for errors\n\t\tif (debug) {\n\t\t\tlog(\n\t\t\t\t`❌ Request [${requestId}] failed with HTTP ${response.status} in ${responseTime}ms`,\n\t\t\t\ttrue\n\t\t\t);\n\t\t\tlog(` URL: ${fullUrl}`, true);\n\t\t\tlog(` Status: ${response.status} ${response.statusText}`, true);\n\t\t\tif (errorBody) {\n\t\t\t\tlog(\n\t\t\t\t\t` Response body: ${errorBody.substring(0, 500)}${errorBody.length > 500 ? '...' : ''}`,\n\t\t\t\t\ttrue\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Check if it's a valid compute response with errors/warnings\n\t\tif (response.status === 500) {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(errorBody);\n\t\t\t\t// If it has values, it's a partial success with errors\n\t\t\t\tif (parsed?.values && (parsed.errors || parsed.warnings)) {\n\t\t\t\t\tif (debug) {\n\t\t\t\t\t\tlog(\n\t\t\t\t\t\t\t`⚠️ Request [${requestId}] completed with Grasshopper errors in ${responseTime}ms`,\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (parsed.errors?.length > 0) {\n\t\t\t\t\t\t\tlog(` Errors: ${JSON.stringify(parsed.errors, null, 2)}`, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (parsed.warnings?.length > 0) {\n\t\t\t\t\t\t\tlog(` Warnings: ${JSON.stringify(parsed.warnings, null, 2)}`, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\n\t\t\t\t// If it's a raw exception from the server (like ArgumentException), include it in the error message\n\t\t\t\tif (parsed?.Message) {\n\t\t\t\t\terrorBody = `${parsed.ExceptionType ? parsed.ExceptionType + ': ' : ''}${parsed.Message}\\n${parsed.StackTrace || ''}`;\n\t\t\t\t} else if (parsed?.error) {\n\t\t\t\t\terrorBody =\n\t\t\t\t\t\ttypeof parsed.error === 'string' ? parsed.error : JSON.stringify(parsed.error, null, 2);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tif (debug) {\n\t\t\t\t\tlog(` Failed to parse error body as JSON: ${e}`, true);\n\t\t\t\t}\n\t\t\t\t// Not valid JSON, proceed with HTTP error\n\t\t\t}\n\t\t}\n\n\t\tthrowHttpError(response, fullUrl, requestId, requestSize, serverUrl, errorBody);\n\t}\n\n\tlog(`✅ Request [${requestId}] completed in ${responseTime}ms`, debug);\n\n\ttry {\n\t\treturn await response.json();\n\t} catch (error) {\n\t\tthrow new RhinoComputeError('Failed to parse JSON response', ErrorCodes.NETWORK_ERROR, {\n\t\t\tstatusCode: response.status,\n\t\t\tcontext: {\n\t\t\t\turl: fullUrl,\n\t\t\t\trequestId\n\t\t\t},\n\t\t\toriginalError: error instanceof Error ? error : new Error(String(error))\n\t\t});\n\t}\n}\n\n// ============================================================================\n// Single attempt\n// ============================================================================\n\ninterface AttemptContext {\n\tendpoint: string;\n\tbody: string;\n\trequestSize: number;\n\tfullUrl: string;\n\trequestId: string;\n\theaders: HeadersInit;\n\tconfig: ComputeConfig | GrasshopperComputeConfig;\n}\n\ninterface AttemptResult {\n\tok: true;\n\tvalue: any;\n}\n\ninterface AttemptRetry {\n\tok: false;\n\tretry: true;\n\tdelayMs: number;\n\tcause: RhinoComputeError;\n}\n\ninterface AttemptFatal {\n\tok: false;\n\tretry: false;\n\tcause: RhinoComputeError;\n}\n\nasync function attemptFetch(\n\tctx: AttemptContext,\n\tretryPolicy: Required<RetryPolicy>,\n\tattempt: number,\n\ttotalAttempts: number\n): Promise<AttemptResult | AttemptRetry | AttemptFatal> {\n\tconst { signal, cleanup } = composeSignal(ctx.config.signal, ctx.config.timeoutMs);\n\tconst startTime = performance.now();\n\n\ttry {\n\t\tconst response = await fetch(ctx.fullUrl, {\n\t\t\tmethod: 'POST',\n\t\t\tbody: ctx.body,\n\t\t\theaders: ctx.headers,\n\t\t\tsignal\n\t\t});\n\n\t\t// 429 with Retry-After or retryable 5xx → maybe retry\n\t\tconst isRetryableStatus =\n\t\t\tRETRYABLE_STATUS.has(response.status) ||\n\t\t\t(retryPolicy.retryOn429 && response.status === 429);\n\n\t\tif (isRetryableStatus && attempt < totalAttempts - 1) {\n\t\t\tconst retryAfterMs = parseRetryAfter(response.headers.get('Retry-After'));\n\t\t\tconst delayMs = retryAfterMs ?? backoffDelay(attempt, retryPolicy);\n\t\t\t// Drain the body so the connection can be reused\n\t\t\tawait response.text().catch(() => {});\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tretry: true,\n\t\t\t\tdelayMs,\n\t\t\t\tcause: new RhinoComputeError(\n\t\t\t\t\t`HTTP ${response.status} ${response.statusText} (will retry)`,\n\t\t\t\t\tErrorCodes.NETWORK_ERROR,\n\t\t\t\t\t{ statusCode: response.status, context: { requestId: ctx.requestId } }\n\t\t\t\t)\n\t\t\t};\n\t\t}\n\n\t\tconst value = await handleResponse(\n\t\t\tresponse,\n\t\t\tctx.fullUrl,\n\t\t\tctx.requestId,\n\t\t\tctx.requestSize,\n\t\t\tctx.config.serverUrl,\n\t\t\tstartTime,\n\t\t\tctx.config.debug\n\t\t);\n\t\treturn { ok: true, value };\n\t} catch (error) {\n\t\t// Caller-aborted vs timeout-aborted distinction\n\t\tif (error instanceof Error && (error.name === 'AbortError' || error.name === 'TimeoutError')) {\n\t\t\tconst callerAborted = ctx.config.signal?.aborted === true;\n\n\t\t\tif (callerAborted) {\n\t\t\t\t// Caller cancellation is never retried — propagate immediately\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tretry: false,\n\t\t\t\t\tcause: new RhinoComputeError('Request aborted by caller', ErrorCodes.UNKNOWN_ERROR, {\n\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\tendpoint: ctx.endpoint,\n\t\t\t\t\t\t\trequestId: ctx.requestId,\n\t\t\t\t\t\t\trequestSize: ctx.requestSize\n\t\t\t\t\t\t},\n\t\t\t\t\t\toriginalError: error\n\t\t\t\t\t})\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Timeout — retryable up to attempts limit\n\t\t\tconst fatal = new RhinoComputeError(\n\t\t\t\t`Request timed out after ${ctx.config.timeoutMs}ms`,\n\t\t\t\tErrorCodes.TIMEOUT_ERROR,\n\t\t\t\t{\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\tserverUrl: ctx.config.serverUrl,\n\t\t\t\t\t\ttimeoutMs: ctx.config.timeoutMs,\n\t\t\t\t\t\turl: ctx.fullUrl,\n\t\t\t\t\t\trequestId: ctx.requestId,\n\t\t\t\t\t\tendpoint: ctx.endpoint,\n\t\t\t\t\t\trequestSize: ctx.requestSize\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t\tif (attempt < totalAttempts - 1) {\n\t\t\t\treturn { ok: false, retry: true, delayMs: backoffDelay(attempt, retryPolicy), cause: fatal };\n\t\t\t}\n\t\t\treturn { ok: false, retry: false, cause: fatal };\n\t\t}\n\n\t\t// Network error (TypeError) — retryable\n\t\tif (error instanceof TypeError) {\n\t\t\tconst fatal = new RhinoComputeError(\n\t\t\t\t`Network error: ${error.message}`,\n\t\t\t\tErrorCodes.NETWORK_ERROR,\n\t\t\t\t{\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\tserverUrl: ctx.config.serverUrl,\n\t\t\t\t\t\turl: ctx.fullUrl,\n\t\t\t\t\t\trequestId: ctx.requestId,\n\t\t\t\t\t\tendpoint: ctx.endpoint,\n\t\t\t\t\t\trequestSize: ctx.requestSize\n\t\t\t\t\t},\n\t\t\t\t\toriginalError: error\n\t\t\t\t}\n\t\t\t);\n\t\t\tif (attempt < totalAttempts - 1) {\n\t\t\t\treturn { ok: false, retry: true, delayMs: backoffDelay(attempt, retryPolicy), cause: fatal };\n\t\t\t}\n\t\t\treturn { ok: false, retry: false, cause: fatal };\n\t\t}\n\n\t\t// RhinoComputeError thrown from handleResponse — already has full context.\n\t\t// Retryable only if it carries a retryable status code.\n\t\tif (error instanceof RhinoComputeError) {\n\t\t\tconst status = error.statusCode;\n\t\t\tconst retryable =\n\t\t\t\tstatus !== undefined &&\n\t\t\t\t(RETRYABLE_STATUS.has(status) || (retryPolicy.retryOn429 && status === 429));\n\t\t\tif (retryable && attempt < totalAttempts - 1) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tretry: true,\n\t\t\t\t\tdelayMs: backoffDelay(attempt, retryPolicy),\n\t\t\t\t\tcause: error\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { ok: false, retry: false, cause: error };\n\t\t}\n\n\t\t// Unknown — wrap and don't retry\n\t\treturn {\n\t\t\tok: false,\n\t\t\tretry: false,\n\t\t\tcause: new RhinoComputeError(\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\tErrorCodes.UNKNOWN_ERROR,\n\t\t\t\t{\n\t\t\t\t\tcontext: { endpoint: ctx.endpoint, requestId: ctx.requestId },\n\t\t\t\t\toriginalError: error instanceof Error ? error : new Error(String(error))\n\t\t\t\t}\n\t\t\t)\n\t\t};\n\t} finally {\n\t\tcleanup();\n\t}\n}\n\n// ============================================================================\n// Main Function\n// ============================================================================\n\n/**\n * Generic Rhino Compute fetch function.\n * Sends a POST request to any Compute endpoint with pre-prepared arguments.\n *\n * Use this for advanced, low-level control over compute requests. For most use cases, prefer higher-level APIs.\n *\n * @typeParam E - The endpoint name (e.g., 'grasshopper', 'io'). Determines the response type for better type safety.\n * @param endpoint - The Compute API endpoint (e.g., 'grasshopper', 'io', 'mesh').\n * @param args - Pre-prepared arguments for the request body.\n * @param config - Compute configuration (server URL, API key, timeout, debug, retry, signal).\n * @returns The parsed JSON response from the server, typed according to the endpoint.\n *\n * @example\n * // Basic usage for the Grasshopper endpoint:\n * const response = await fetchRhinoCompute(\n * 'grasshopper',\n * { ... },\n * {\n * serverUrl: 'https://my-server.com',\n * debug: true,\n * timeoutMs: 30_000,\n * retry: { attempts: 2 },\n * signal: controller.signal,\n * }\n * );\n */\nexport async function fetchRhinoCompute<E extends Endpoint>(\n\tendpoint: E,\n\targs: Record<string, any>,\n\tconfig: ComputeConfig | GrasshopperComputeConfig\n): Promise<ComputeResponseFor<E>> {\n\tconst requestId = generateRequestId();\n\tconst body = JSON.stringify(args);\n\tconst requestSize = body.length;\n\tconst fullUrl = buildUrl(endpoint, config.serverUrl);\n\tconst headers = buildHeaders(requestId, config);\n\tconst retryPolicy = resolveRetryPolicy(config.retry);\n\tconst totalAttempts = retryPolicy.attempts + 1;\n\n\tif (config.debug) {\n\t\tconst sizeKb = (requestSize / 1024).toFixed(2);\n\t\tconst emoji = requestSize > 100000 ? '⚠️' : '🚀';\n\t\tlog(`${emoji} Starting compute request [${requestId}]: ${endpoint} (${sizeKb}KB)`, true);\n\t}\n\n\tconst ctx: AttemptContext = {\n\t\tendpoint,\n\t\tbody,\n\t\trequestSize,\n\t\tfullUrl,\n\t\trequestId,\n\t\theaders,\n\t\tconfig\n\t};\n\n\tlet lastError: RhinoComputeError | null = null;\n\n\tfor (let attempt = 0; attempt < totalAttempts; attempt++) {\n\t\tconst result = await attemptFetch(ctx, retryPolicy, attempt, totalAttempts);\n\n\t\tif (result.ok) return result.value as ComputeResponseFor<E>;\n\n\t\tif (!result.retry) throw result.cause;\n\n\t\tlastError = result.cause;\n\t\tif (config.debug) {\n\t\t\tlog(\n\t\t\t\t`🔁 Request [${requestId}] retrying after ${result.delayMs}ms (attempt ${attempt + 2}/${totalAttempts}): ${result.cause.message}`,\n\t\t\t\ttrue\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tawait sleep(result.delayMs, config.signal);\n\t\t} catch {\n\t\t\t// Caller cancelled during backoff\n\t\t\tthrow new RhinoComputeError('Request aborted by caller', ErrorCodes.UNKNOWN_ERROR, {\n\t\t\t\tcontext: { endpoint, requestId, requestSize },\n\t\t\t\toriginalError: lastError\n\t\t\t});\n\t\t}\n\t}\n\n\t// Exhausted retries — throw the last seen error\n\tthrow (\n\t\tlastError ??\n\t\tnew RhinoComputeError('Unknown error after retries', ErrorCodes.UNKNOWN_ERROR, {\n\t\t\tcontext: { endpoint, requestId, requestSize }\n\t\t})\n\t);\n}\n","import { RhinoComputeError, ErrorCodes } from '../errors';\nimport { getLogger } from '../utils/logger';\n\n/**\n * ComputeServerStats provides methods to query Rhino Compute server statistics.\n *\n * @public Use this for server health monitoring and statistics.\n *\n * @example\n * ```typescript\n * const stats = new ComputeServerStats('http://localhost:6500', 'your-api-key');\n *\n * try {\n * const isOnline = await stats.isServerOnline();\n * const children = await stats.getActiveChildren();\n * const version = await stats.getVersion();\n *\n * // Or get everything at once\n * const allStats = await stats.getServerStats();\n * } finally {\n * await stats.dispose(); // Clean up resources\n * }\n * ```\n */\nexport default class ComputeServerStats {\n\tprivate readonly serverUrl: string;\n\tprivate readonly apiKey?: string;\n\tprivate disposed = false;\n\tprivate activeMonitors: Set<() => void> = new Set();\n\tprivate activeTimeouts: Set<ReturnType<typeof setTimeout>> = new Set();\n\n\t/**\n\t * @param serverUrl - Base URL of the Rhino Compute server with http:// or https:// scheme (e.g., 'http://localhost:6500')\n\t * @param apiKey - Optional API key for authentication\n\t */\n\tconstructor(serverUrl: string, apiKey?: string) {\n\t\tif (!serverUrl?.trim()) {\n\t\t\tthrow new RhinoComputeError('serverUrl is required', ErrorCodes.INVALID_CONFIG, {\n\t\t\t\tcontext: { serverUrl }\n\t\t\t});\n\t\t}\n\n\t\t// Validate URL has http:// or https:// scheme\n\t\tif (!serverUrl.match(/^https?:\\/\\//)) {\n\t\t\tthrow new RhinoComputeError(\n\t\t\t\t`Invalid serverUrl: \"${serverUrl}\". Must start with \"http://\" or \"https://\". ` +\n\t\t\t\t\t`For example: \"http://localhost:5000\" or \"https://example.com\"`,\n\t\t\t\tErrorCodes.INVALID_CONFIG,\n\t\t\t\t{ context: { serverUrl } }\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tnew URL(serverUrl);\n\t\t} catch (err) {\n\t\t\tthrow new RhinoComputeError(\n\t\t\t\t`Invalid serverUrl: \"${serverUrl}\". Must be a valid URL. ` +\n\t\t\t\t\t`Received error: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t\tErrorCodes.INVALID_CONFIG,\n\t\t\t\t{\n\t\t\t\t\tcontext: { serverUrl },\n\t\t\t\t\toriginalError: err instanceof Error ? err : undefined\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tthis.apiKey = apiKey;\n\t\tthis.serverUrl = serverUrl.replace(/\\/+$/, '');\n\t}\n\n\t/**\n\t * Build request headers with optional API key.\n\t */\n\tprivate buildHeaders(): HeadersInit {\n\t\tconst headers: HeadersInit = {\n\t\t\t'Content-Type': 'application/json'\n\t\t};\n\n\t\tif (this.apiKey) {\n\t\t\theaders['RhinoComputeKey'] = this.apiKey;\n\t\t}\n\n\t\treturn headers;\n\t}\n\n\t/**\n\t * Check if the server is online.\n\t */\n\tpublic async isServerOnline(): Promise<boolean> {\n\t\tthis.ensureNotDisposed();\n\n\t\tconst url = `${this.serverUrl}/healthcheck`;\n\t\tconst init: RequestInit = { headers: this.buildHeaders(), method: 'GET' };\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, init);\n\n\t\t\treturn response.ok;\n\t\t} catch (err) {\n\t\t\tgetLogger().debug('[ComputeServerStats] Fetch error:', err);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Get the number of active child processes on the server.\n\t *\n\t * @returns Number of active children, or null if unavailable\n\t */\n\tpublic async getActiveChildren(): Promise<number | null> {\n\t\tthis.ensureNotDisposed();\n\n\t\ttry {\n\t\t\tconst response = await fetch(`${this.serverUrl}/activechildren`, {\n\t\t\t\theaders: this.buildHeaders()\n\t\t\t});\n\t\t\tif (!response.ok) {\n\t\t\t\tgetLogger().warn('[ComputeServerStats] Failed to fetch active children:', response.status);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst text = await response.text();\n\t\t\tconst count = parseInt(text.trim(), 10);\n\n\t\t\tif (isNaN(count)) {\n\t\t\t\tgetLogger().warn('[ComputeServerStats] Invalid active children response:', text);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn count;\n\t\t} catch (err) {\n\t\t\tgetLogger().warn('[ComputeServerStats] Error fetching active children:', err);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the server version information.\n\t *\n\t * @returns Version object with rhino, compute, and git_sha, or null if unavailable\n\t */\n\tpublic async getVersion(): Promise<{\n\t\trhino: string;\n\t\tcompute: string;\n\t\tgit_sha: string | null;\n\t} | null> {\n\t\tthis.ensureNotDisposed();\n\n\t\ttry {\n\t\t\tconst response = await fetch(`${this.serverUrl}/version`, {\n\t\t\t\theaders: this.buildHeaders()\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tgetLogger().warn('[ComputeServerStats] Failed to fetch version:', response.status);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Read body as text first, then try JSON.parse — avoids the\n\t\t\t// \"Body has already been read\" error if response.json() fails.\n\t\t\tconst text = await response.text();\n\t\t\ttry {\n\t\t\t\tconst json = JSON.parse(text);\n\t\t\t\treturn {\n\t\t\t\t\trhino: json.rhino ?? '',\n\t\t\t\t\tcompute: json.compute ?? '',\n\t\t\t\t\tgit_sha: json.git_sha ?? null\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\treturn { rhino: text, compute: '', git_sha: null };\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tgetLogger().warn('[ComputeServerStats] Error fetching version:', err);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get comprehensive server statistics.\n\t * Fetches all available server information in parallel.\n\t *\n\t * @returns Object containing server status and available stats\n\t */\n\tpublic async getServerStats(): Promise<{\n\t\tisOnline: boolean;\n\t\tversion?: { rhino: string; compute: string; git_sha: string | null };\n\t\tactiveChildren?: number;\n\t}> {\n\t\tthis.ensureNotDisposed();\n\n\t\tconst isOnline = await this.isServerOnline();\n\n\t\tif (!isOnline) {\n\t\t\treturn { isOnline: false };\n\t\t}\n\n\t\tconst [version, activeChildren] = await Promise.all([\n\t\t\tthis.getVersion(),\n\t\t\tthis.getActiveChildren()\n\t\t]);\n\n\t\treturn {\n\t\t\tisOnline: true,\n\t\t\t...(version && { version }),\n\t\t\t...(activeChildren !== null && { activeChildren })\n\t\t};\n\t}\n\n\t/**\n\t * Continuously monitor server stats at specified interval.\n\t *\n\t * @param callback - Function called with stats on each interval\n\t * @param intervalMs - Milliseconds between checks (default: 5000)\n\t * @returns Function to stop monitoring\n\t *\n\t * @example\n\t * ```typescript\n\t * const stopMonitoring = stats.monitor((data) => {\n\t * console.log('Server stats:', data);\n\t * }, 3000);\n\t *\n\t * // Later...\n\t * stopMonitoring();\n\t * ```\n\t */\n\tpublic monitor(\n\t\tcallback: (stats: Awaited<ReturnType<typeof this.getServerStats>>) => void,\n\t\tintervalMs: number = 5000\n\t): () => void {\n\t\tthis.ensureNotDisposed();\n\n\t\tlet active = true;\n\t\tlet currentTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n\t\tgetLogger().info(`🔄 Starting server stats monitoring every ${intervalMs}ms`);\n\n\t\tconst check = async () => {\n\t\t\t// Clear current timeout from tracking since it has fired\n\t\t\tif (currentTimeoutId !== null) {\n\t\t\t\tthis.activeTimeouts.delete(currentTimeoutId);\n\t\t\t\tcurrentTimeoutId = null;\n\t\t\t}\n\n\t\t\tif (!active || this.disposed) return;\n\n\t\t\ttry {\n\t\t\t\tconst _stats = await this.getServerStats();\n\n\t\t\t\t// Check again after async operation to prevent race condition\n\t\t\t\tif (!active || this.disposed) return;\n\n\t\t\t\ttry {\n\t\t\t\t\tcallback(_stats);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tgetLogger().error('[ComputeServerStats] Monitor callback threw:', err);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tgetLogger().error('[ComputeServerStats] Failed to fetch stats during monitor:', err);\n\t\t\t}\n\n\t\t\tif (active && !this.disposed) {\n\t\t\t\tcurrentTimeoutId = setTimeout(() => void check(), intervalMs);\n\t\t\t\tthis.activeTimeouts.add(currentTimeoutId);\n\t\t\t}\n\t\t};\n\n\t\tconst stopMonitoring = () => {\n\t\t\tactive = false;\n\n\t\t\t// Clear any pending timeout\n\t\t\tif (currentTimeoutId !== null) {\n\t\t\t\tclearTimeout(currentTimeoutId);\n\t\t\t\tthis.activeTimeouts.delete(currentTimeoutId);\n\t\t\t\tcurrentTimeoutId = null;\n\t\t\t}\n\n\t\t\tthis.activeMonitors.delete(stopMonitoring);\n\t\t};\n\n\t\tthis.activeMonitors.add(stopMonitoring);\n\n\t\t// Explicitly mark as fire-and-forget since we don't need to await the initial call\n\t\tvoid check();\n\n\t\treturn stopMonitoring;\n\t}\n\n\t/**\n\t * Disposes of all resources and stops all active monitors.\n\t * Call this when you're done using the stats instance.\n\t */\n\tpublic async dispose(): Promise<void> {\n\t\tif (this.disposed) return;\n\n\t\tthis.disposed = true;\n\n\t\t// Stop all active monitors (this will also clear their timeouts)\n\t\tfor (const stopMonitor of this.activeMonitors) {\n\t\t\tstopMonitor();\n\t\t}\n\t\tthis.activeMonitors.clear();\n\n\t\t// Clear any remaining timeouts (defensive cleanup)\n\t\tfor (const timeoutId of this.activeTimeouts) {\n\t\t\tclearTimeout(timeoutId);\n\t\t}\n\t\tthis.activeTimeouts.clear();\n\t}\n\n\t/**\n\t * Ensures the instance hasn't been disposed.\n\t */\n\tprivate ensureNotDisposed(): void {\n\t\tif (this.disposed) {\n\t\t\tthrow new RhinoComputeError(\n\t\t\t\t'ComputeServerStats has been disposed and cannot be used',\n\t\t\t\tErrorCodes.INVALID_STATE,\n\t\t\t\t{ context: { disposed: this.disposed } }\n\t\t\t);\n\t\t}\n\t}\n}\n","/**\n * Converts a string to camelCase.\n * @param str - The string to convert\n * @param options - Options object\n * - preserveSpaces: If true, spaces are preserved (default: false)\n */\nexport function toCamelCase(str: string, options: { preserveSpaces?: boolean } = {}): string {\n\tconst { preserveSpaces = false } = options;\n\tlet s = str.trim();\n\tif (!preserveSpaces) {\n\t\t// Remove spaces, dashes, and underscores, camelCase the next letter\n\t\ts = s\n\t\t\t.replace(/^[A-Z]/, (m) => m.toLowerCase())\n\t\t\t.replace(/[\\s-_]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''));\n\t\treturn s;\n\t} else {\n\t\t// Only camelCase after dashes/underscores, preserve spaces\n\t\ts =\n\t\t\ts.charAt(0).toLowerCase() +\n\t\t\ts.slice(1).replace(/[-_](.)/g, (_, c) => (c ? c.toUpperCase() : ''));\n\t\treturn s;\n\t}\n}\n\n/**\n * Recursively converts all object keys to camelCase.\n * @param obj - The object to process\n * @param options - Options object\n * - deep: If true, process deeply\n * - preserveSpaces: If true, spaces are preserved in keys\n * @returns The new object with camelCased keys\n * @internal\n */\nexport function camelcaseKeys(\n\tobj: unknown,\n\toptions: { deep?: boolean; preserveSpaces?: boolean } = {}\n): unknown {\n\tif (!obj || typeof obj !== 'object') {\n\t\treturn obj;\n\t}\n\n\tif (Array.isArray(obj)) {\n\t\treturn options.deep ? obj.map((item) => camelcaseKeys(item, options)) : obj;\n\t}\n\n\treturn Object.keys(obj).reduce(\n\t\t(result, key) => {\n\t\t\tconst camelKey = toCamelCase(key, { preserveSpaces: options.preserveSpaces });\n\t\t\tconst value = (obj as any)[key];\n\t\t\t(result as any)[camelKey] = options.deep ? camelcaseKeys(value, options) : value;\n\t\t\treturn result;\n\t\t},\n\t\t{} as Record<string, unknown>\n\t);\n}\n"],"mappings":"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","names":["ErrorCodes","RhinoComputeError","_RhinoComputeError","message","code","options","__publicField","inputName","reason","context","ErrorCodes","expectedType","defaultValue","availableValues","paramType","paramName","expectedStructure","NoOpLogger","ConsoleLogger","message","args","internalLogger","getLogger","setLogger","logger","enableDebugLogging","DEFAULT_RETRY","RETRYABLE_STATUS","resolveRetryPolicy","policy","parseRetryAfter","headerValue","seconds","dateMs","delta","backoffDelay","attempt","exponential","jitter","sleep","ms","signal","resolve","reject","id","onAbort","throwHttpError","response","fullUrl","requestId","requestSize","serverUrl","errorBody","status","statusText","context","bodyHint","error","ErrorCodes","RhinoComputeError","buildUrl","endpoint","base","path","isLocalhost","host","buildHeaders","config","headers","getLogger","generateRequestId","log","message","debug","composeSignal","callerSignal","timeoutMs","signals","cleanup","ctrl","s","prevCleanup","handleResponse","startTime","responseTime","parsed","e","attemptFetch","ctx","retryPolicy","totalAttempts","delayMs","fatal","fetchRhinoCompute","args","body","sizeKb","emoji","lastError","result","ComputeServerStats","serverUrl","apiKey","__publicField","RhinoComputeError","ErrorCodes","err","headers","url","init","getLogger","response","text","count","json","version","activeChildren","callback","intervalMs","active","currentTimeoutId","check","_stats","stopMonitoring","stopMonitor","timeoutId","toCamelCase","str","options","preserveSpaces","s","_","c","m","camelcaseKeys","obj","item","result","key","camelKey","value"]}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunk2NFN5ERTcjs = require('./chunk-2NFN5ERT.cjs');var _chunkXULONXVPcjs = require('./chunk-XULONXVP.cjs');function L(t){let e=new WeakSet,r=n=>{if(n==null)return JSON.stringify(n);if(typeof n=="number")return Number.isFinite(n)?String(n):JSON.stringify(null);if(typeof n=="string"||typeof n=="boolean")return JSON.stringify(n);if(typeof n=="bigint")return JSON.stringify(n.toString());if(n instanceof Uint8Array){let o=n.length>64?Array.from(n.slice(0,32)).concat(Array.from(n.slice(-32))):Array.from(n);return JSON.stringify({__u8:!0,len:n.length,sample:o})}return Array.isArray(n)?`[${n.map(r).join(",")}]`:typeof n=="object"?e.has(n)?JSON.stringify("[Circular]"):(e.add(n),`{${Object.keys(n).sort().map(a=>`${JSON.stringify(a)}:${r(n[a])}`).join(",")}}`):JSON.stringify(null)};return r(t)}function J(t){let e=2166136261;for(let r=0;r<t.length;r++)e^=t.charCodeAt(r),e=e+((e<<1)+(e<<4)+(e<<7)+(e<<8)+(e<<24))>>>0;return e.toString(16).padStart(8,"0")}function v(t,e){let r=typeof t=="string"?t:L({__u8:!0,len:t.length});return J(`${r}|${L(e)}`)}var h=class{constructor(e,r,n={}){_chunkXULONXVPcjs.b.call(void 0, this,"executor");_chunkXULONXVPcjs.b.call(void 0, this,"baseConfig");_chunkXULONXVPcjs.b.call(void 0, this,"mode");_chunkXULONXVPcjs.b.call(void 0, this,"maxConcurrent");_chunkXULONXVPcjs.b.call(void 0, this,"timeoutMs");_chunkXULONXVPcjs.b.call(void 0, this,"retry");_chunkXULONXVPcjs.b.call(void 0, this,"cacheEnabled");_chunkXULONXVPcjs.b.call(void 0, this,"cacheMax");_chunkXULONXVPcjs.b.call(void 0, this,"cacheTtl");_chunkXULONXVPcjs.b.call(void 0, this,"cache",new Map);_chunkXULONXVPcjs.b.call(void 0, this,"onStart");_chunkXULONXVPcjs.b.call(void 0, this,"onSettle");_chunkXULONXVPcjs.b.call(void 0, this,"onSuperseded");_chunkXULONXVPcjs.b.call(void 0, this,"subscribers",new Set);_chunkXULONXVPcjs.b.call(void 0, this,"inFlight",new Set);_chunkXULONXVPcjs.b.call(void 0, this,"pendingForLatestWins",null);_chunkXULONXVPcjs.b.call(void 0, this,"fifoQueue",[]);_chunkXULONXVPcjs.b.call(void 0, this,"_lastResult",null);_chunkXULONXVPcjs.b.call(void 0, this,"_lastError",null);_chunkXULONXVPcjs.b.call(void 0, this,"_lastDurationMs",null);_chunkXULONXVPcjs.b.call(void 0, this,"disposed",!1);this.executor=e,this.baseConfig=r,this.mode=_nullishCoalesce(n.mode, () => ("latest-wins")),this.maxConcurrent=Math.max(1,_nullishCoalesce(n.maxConcurrent, () => ((this.mode==="parallel"?4:1)))),this.timeoutMs=n.timeoutMs,this.retry=n.retry;let o=n.cache;this.cacheEnabled=o!==void 0&&o!==!1;let s=typeof o=="object"?o:{};this.cacheMax=_nullishCoalesce(s.maxEntries, () => (50)),this.cacheTtl=_nullishCoalesce(s.ttlMs, () => (0)),this.onStart=n.onStart,this.onSettle=n.onSettle,this.onSuperseded=n.onSuperseded}get isSolving(){return this.inFlight.size>0}get hasPending(){return this.pendingForLatestWins!==null||this.fifoQueue.length>0}get inFlightCount(){return this.inFlight.size}get queueDepth(){return this.fifoQueue.length+(this.pendingForLatestWins?1:0)}get lastResult(){return this._lastResult}get lastError(){return this._lastError}get lastDurationMs(){return this._lastDurationMs}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(){for(let e of this.subscribers)try{e()}catch(r){_chunkXULONXVPcjs.e.call(void 0, ).error("[SolveScheduler] subscriber threw:",r)}}solve(e,r,n){if(this.disposed)return Promise.reject(new (0, _chunkXULONXVPcjs.d)("SolveScheduler has been disposed and cannot be used",_chunkXULONXVPcjs.c.INVALID_STATE));let o=v(e,r),s={key:o,enqueuedAt:Date.now(),startedAt:null};if(this.cacheEnabled){let a=this.readCache(o);if(a){let i={status:"success",response:a,durationMs:0,fromCache:!0};return this._lastResult=a,this._lastError=null,this._lastDurationMs=0,this.runHook(this.onStart,s),this.runHook(this.onSettle,s,i),this.notify(),Promise.resolve(a)}}return new Promise((a,i)=>{let u={definition:e,dataTree:r,ctx:s,resolve:a,reject:i,externalSignal:_optionalChain([n, 'optionalAccess', _2 => _2.signal])};if(_optionalChain([u, 'access', _3 => _3.externalSignal, 'optionalAccess', _4 => _4.aborted])){i(this.makeAbortError(s));return}this.enqueue(u)})}enqueue(e){switch(this.mode){case"latest-wins":{this.pendingForLatestWins&&(this.supersede(this.pendingForLatestWins),this.pendingForLatestWins=null);for(let r of this.inFlight)this.supersede(r),r.controller.abort();this.inFlight.size===0?this.execute(e):this.pendingForLatestWins=e;break}case"queue":{this.inFlight.size<this.maxConcurrent?this.execute(e):this.fifoQueue.push(e);break}case"parallel":{this.inFlight.size<this.maxConcurrent?this.execute(e):this.fifoQueue.push(e);break}}this.notify()}async execute(e){let r=new AbortController,n={...e,controller:r};this.inFlight.add(n),e.ctx.startedAt=Date.now();let o=()=>r.abort();_optionalChain([e, 'access', _5 => _5.externalSignal, 'optionalAccess', _6 => _6.addEventListener, 'call', _7 => _7("abort",o,{once:!0})]),this.runHook(this.onStart,e.ctx),this.notify();let s=performance.now();try{let a={...this.baseConfig,signal:r.signal,...this.timeoutMs!==void 0&&{timeoutMs:this.timeoutMs},...this.retry!==void 0&&{retry:this.retry}},i=await this.executor(e.definition,e.dataTree,a),u=performance.now()-s;this.cacheEnabled&&this.writeCache(e.ctx.key,i),this._lastResult=i,this._lastError=null,this._lastDurationMs=u,e.resolve(i),this.runHook(this.onSettle,e.ctx,{status:"success",response:i,durationMs:u,fromCache:!1})}catch(a){let i=performance.now()-s,u=a instanceof _chunkXULONXVPcjs.d?a:new (0, _chunkXULONXVPcjs.d)(a instanceof Error?a.message:String(a),_chunkXULONXVPcjs.c.UNKNOWN_ERROR,{originalError:a instanceof Error?a:new Error(String(a))});this._lastError=u,this._lastDurationMs=i,e.reject(u),this.runHook(this.onSettle,e.ctx,{status:"error",error:u,durationMs:i})}finally{_optionalChain([e, 'access', _8 => _8.externalSignal, 'optionalAccess', _9 => _9.removeEventListener, 'call', _10 => _10("abort",o)]),this.inFlight.delete(n),this.drainNext(),this.notify()}}drainNext(){if(!this.disposed){if(this.mode==="latest-wins"){if(this.pendingForLatestWins&&this.inFlight.size===0){let e=this.pendingForLatestWins;this.pendingForLatestWins=null,this.execute(e)}return}for(;this.fifoQueue.length>0&&this.inFlight.size<this.maxConcurrent;){let e=this.fifoQueue.shift();this.execute(e)}}}supersede(e){let r=new (0, _chunkXULONXVPcjs.d)("Superseded by newer solve",_chunkXULONXVPcjs.c.UNKNOWN_ERROR,{context:{key:e.ctx.key,enqueuedAt:e.ctx.enqueuedAt}});e.reject(r),this.runHook(this.onSuperseded,e.ctx)}makeAbortError(e){return new (0, _chunkXULONXVPcjs.d)("Request aborted by caller",_chunkXULONXVPcjs.c.UNKNOWN_ERROR,{context:{key:e.key,enqueuedAt:e.enqueuedAt}})}cancelAll(){for(this.pendingForLatestWins&&(this.pendingForLatestWins.reject(this.makeAbortError(this.pendingForLatestWins.ctx)),this.pendingForLatestWins=null);this.fifoQueue.length>0;){let e=this.fifoQueue.shift();e.reject(this.makeAbortError(e.ctx))}for(let e of this.inFlight)e.controller.abort();this.notify()}readCache(e){if(!this.cacheEnabled)return null;let r=this.cache.get(e);return r?this.cacheTtl>0&&Date.now()-r.insertedAt>this.cacheTtl?(this.cache.delete(e),null):(this.cache.delete(e),this.cache.set(e,r),r.response):null}writeCache(e,r){if(this.cacheEnabled)for(this.cache.set(e,{response:r,insertedAt:Date.now()});this.cache.size>this.cacheMax;){let n=this.cache.keys().next().value;if(n===void 0)break;this.cache.delete(n)}}clearCache(){this.cache.clear()}dispose(){this.disposed||(this.disposed=!0,this.cancelAll(),this.subscribers.clear(),this.cache.clear())}runHook(e,...r){if(e)try{e(...r)}catch(n){_chunkXULONXVPcjs.e.call(void 0, ).error("[SolveScheduler] hook threw:",n)}}};var T=class t{constructor(e){_chunkXULONXVPcjs.b.call(void 0, this,"config");_chunkXULONXVPcjs.b.call(void 0, this,"serverStats");_chunkXULONXVPcjs.b.call(void 0, this,"disposed",!1);this.config=this.normalizeComputeConfig(e),this.serverStats=new (0, _chunkXULONXVPcjs.i)(this.config.serverUrl,this.config.apiKey)}static async create(e){let r=new t(e);if(!await r.serverStats.isServerOnline())throw new (0, _chunkXULONXVPcjs.d)("Rhino Compute server is not online",_chunkXULONXVPcjs.c.NETWORK_ERROR,{context:{serverUrl:r.config.serverUrl}});return r}getConfig(){return this.ensureNotDisposed(),{...this.config}}async getIO(e){return this.ensureNotDisposed(),R(e,this.config)}async getRawIO(e){return this.ensureNotDisposed(),S(e,this.config)}async solve(e,r,n){this.ensureNotDisposed();try{if(typeof e=="string"&&!_optionalChain([e, 'optionalAccess', _11 => _11.trim, 'call', _12 => _12()]))throw new (0, _chunkXULONXVPcjs.d)("Definition URL/content is required",_chunkXULONXVPcjs.c.INVALID_INPUT,{context:{receivedUrl:e}});if(e instanceof Uint8Array&&e.length===0)throw new (0, _chunkXULONXVPcjs.d)("Definition content is empty",_chunkXULONXVPcjs.c.INVALID_INPUT);let o={...this.config,..._optionalChain([n, 'optionalAccess', _13 => _13.signal])!==void 0&&{signal:n.signal},..._optionalChain([n, 'optionalAccess', _14 => _14.timeoutMs])!==void 0&&{timeoutMs:n.timeoutMs},..._optionalChain([n, 'optionalAccess', _15 => _15.retry])!==void 0&&{retry:n.retry}},s=await x(r,e,o);if(s&&typeof s=="object"&&"message"in s&&!("fileData"in s))throw new (0, _chunkXULONXVPcjs.d)(s.message||"Computation failed",_chunkXULONXVPcjs.c.COMPUTATION_ERROR,{context:{definition:typeof e=="string"&&e.length<200?e:"...content...",inputs:r}});return s}catch(o){throw this.config.debug&&_chunkXULONXVPcjs.e.call(void 0, ).error("Compute failed:",o),o instanceof _chunkXULONXVPcjs.d?o:new (0, _chunkXULONXVPcjs.d)(o instanceof Error?o.message:String(o),_chunkXULONXVPcjs.c.COMPUTATION_ERROR,{context:{definition:typeof e=="string"&&e.length<200?e:"...content...",inputs:r},originalError:o instanceof Error?o:new Error(String(o))})}}createScheduler(e){this.ensureNotDisposed();let r=(n,o,s)=>x(o,n,s);return new h(r,this.config,e)}async dispose(){this.disposed||(this.disposed=!0,"dispose"in this.serverStats&&typeof this.serverStats.dispose=="function"&&await this.serverStats.dispose())}ensureNotDisposed(){if(this.disposed)throw new (0, _chunkXULONXVPcjs.d)("GrasshopperClient has been disposed and cannot be used",_chunkXULONXVPcjs.c.INVALID_STATE)}normalizeComputeConfig(e){if(!_optionalChain([e, 'access', _16 => _16.serverUrl, 'optionalAccess', _17 => _17.trim, 'call', _18 => _18()]))throw new (0, _chunkXULONXVPcjs.d)("serverUrl is required",_chunkXULONXVPcjs.c.INVALID_CONFIG,{context:{receivedServerUrl:e.serverUrl}});try{new URL(e.serverUrl)}catch (e2){throw new (0, _chunkXULONXVPcjs.d)("serverUrl must be a valid URL",_chunkXULONXVPcjs.c.INVALID_CONFIG,{context:{receivedServerUrl:e.serverUrl}})}if(e.serverUrl===""||e.serverUrl==="https://compute.rhino3d.com/")throw new (0, _chunkXULONXVPcjs.d)("serverUrl must be set to your Compute server URL. The default public endpoint is not allowed.",_chunkXULONXVPcjs.c.INVALID_CONFIG,{context:{receivedServerUrl:e.serverUrl}});return{...e,serverUrl:e.serverUrl.replace(/\/+$/,""),apiKey:e.apiKey,authToken:e.authToken,debug:_nullishCoalesce(e.debug, () => (!1)),suppressClientSideWarning:e.suppressClientSideWarning}}};var M=async(t,e=null)=>{try{return await K(t,e)}catch(r){throw new (0, _chunkXULONXVPcjs.d)("Failed to extract files from compute response",_chunkXULONXVPcjs.c.INVALID_STATE,{context:{originalError:r instanceof Error?r.message:String(r)},originalError:r instanceof Error?r:void 0})}},P= exports.e =async(t,e,r=null)=>{if(typeof document>"u"||typeof Blob>"u")throw new (0, _chunkXULONXVPcjs.d)("File download functionality is only available in browser environments. This function requires the DOM API (document, Blob).",_chunkXULONXVPcjs.c.BROWSER_ONLY,{context:{environment:typeof window<"u"?"browser (SSR)":"Node.js",documentAvailable:typeof document<"u",blobAvailable:typeof Blob<"u"}});try{let n=await K(t,r);await ie(n,e)}catch(n){throw n instanceof _chunkXULONXVPcjs.d?n:new (0, _chunkXULONXVPcjs.d)("Failed to download files from compute response",_chunkXULONXVPcjs.c.INVALID_STATE,{context:{originalError:n instanceof Error?n.message:String(n)},originalError:n instanceof Error?n:void 0})}},K=async(t,e)=>{let r=[];if(t.forEach(n=>{let o=`${n.fileName}${n.fileType}`;if(n.subFolder&&n.subFolder.trim()!==""&&(o=`${n.subFolder}/${o}`),n.isBase64Encoded===!0&&n.data){let s=_chunk2NFN5ERTcjs.c.call(void 0, n.data);r.push({fileName:`${n.fileName}${n.fileType}`,content:new Uint8Array(s.buffer),path:o})}else n.isBase64Encoded===!1&&n.data&&r.push({fileName:`${n.fileName}${n.fileType}`,content:n.data,path:o})}),e){let n=Array.isArray(e)?e:[e],o=await Promise.all(n.map(async s=>{try{let a=await fetch(s.filePath);if(!a.ok)return _chunkXULONXVPcjs.e.call(void 0, ).warn(`Failed to fetch additional file from URL: ${s.filePath}`),null;let u=await(await a.blob()).arrayBuffer();return{fileName:s.fileName,content:new Uint8Array(u),path:s.fileName}}catch(a){return _chunkXULONXVPcjs.e.call(void 0, ).error(`Error fetching additional file from URL: ${s.filePath}`,a),null}}));r.push(...o.filter(s=>s!==null))}return r};async function ie(t,e){let{zipSync:r,strToU8:n}=await Promise.resolve().then(() => _interopRequireWildcard(require("fflate"))),o={};t.forEach(i=>{o[i.path]=typeof i.content=="string"?n(i.content):i.content});let s=r(o,{level:6}),a=new Blob([s],{type:"application/zip"});ue(a,`${e}.zip`)}function ue(t,e){if(typeof document>"u")throw new (0, _chunkXULONXVPcjs.d)("saveFile requires a browser environment with DOM API access.",_chunkXULONXVPcjs.c.BROWSER_ONLY,{context:{function:"saveFile",requiredAPI:"document"}});let r=document.createElement("a");r.href=URL.createObjectURL(t),r.download=e,r.click(),URL.revokeObjectURL(r.href)}var A=new Map;function H(t,e){A.set(t,e)}H("Rhino.Geometry.Point3d",(t,e)=>{let r=e;return!r||typeof r.X!="number"?null:new t.Point([r.X,r.Y,r.Z])});H("Rhino.Geometry.Line",(t,e)=>{let r=e;return!r||!r.From||!r.To?null:new t.Line([r.From.X,r.From.Y,r.From.Z],[r.To.X,r.To.Y,r.To.Z])});function le(t){if(A.has(t))return A.get(t);for(let[e,r]of A)if(t.startsWith(e))return r}function pe(t){return!t||typeof t!="object"?null:_nullishCoalesce(_nullishCoalesce(t.data, () => (t.value)), () => (null))}function Y(t,e,r){let n=le(e);if(n)try{return n(r,t)}catch(o){_chunkXULONXVPcjs.e.call(void 0, ).warn(`Failed to decode Rhino type ${e}:`,o)}try{let o=pe(t);if(o)return r.CommonObject.decode(o)}catch(o){return _chunkXULONXVPcjs.e.call(void 0, ).warn(`Failed to decode ${e} with CommonObject:`,o),{__decodeError:!0,type:e,raw:t}}return t}var C={STRING:"System.String",INT:"System.Int32",DOUBLE:"System.Double",BOOL:"System.Boolean"},ce="Rhino.Geometry.",fe=["WebDisplay"],me="FileData";function Q(t){return fe.some(e=>t.includes(e))}function X(t){if(typeof t!="string")return t;let e=t.trim();if(!(e.startsWith("{")||e.startsWith("[")||e.startsWith('"')))return t;try{let n=JSON.parse(e);if(typeof n=="string")try{return JSON.parse(n)}catch (e3){return n}return n}catch (e4){return t}}function de(t,e,r){switch(e){case C.STRING:return typeof t!="string"?t:t.replace(/^"(.*)"$/,"$1");case C.INT:return Number.parseInt(t,10);case C.DOUBLE:return Number.parseFloat(t);case C.BOOL:return String(t).toLowerCase()==="true";default:return r&&e.startsWith(ce)?Y(t,e,r):t}}function Z(t,e,r,n){if(typeof t!="string")return t;let o=r?X(t):t;return de(o,e,n)}function E(t,e){for(let r of Object.values(t))if(Array.isArray(r))for(let n of r)e(n)}function ee(t,e=!1,r={}){let{parseValues:n=!0,rhino:o,stringOnly:s=!1}=r,a={};for(let i of t.values)E(i.InnerTree,u=>{if(Q(u.type)||s&&u.type!==C.STRING)return;let c=e?u.id:i.ParamName;if(!c)return;let d=Z(u.data,u.type,n,o);a[c]===void 0?a[c]=d:Array.isArray(a[c])?a[c].push(d):a[c]=[a[c],d]});return{values:a}}function te(t){let e=[];for(let r of t.values)E(r.InnerTree,n=>{if(!n.type.includes(me))return;let o=X(n.data);o&&o.fileName&&o.fileType&&"data"in o&&typeof o.isBase64Encoded=="boolean"&&typeof o.subFolder=="string"&&e.push(o)});return e}function k(t,e,r={}){let{parseValues:n=!0,rhino:o,stringOnly:s=!1}=r,a;if("byName"in e?a=t.values.find(u=>u.ParamName===e.byName):a=t.values.find(u=>{let c=!1;return E(u.InnerTree,d=>{d.id===e.byId&&(c=!0)}),c}),!a)return;let i=[];if(E(a.InnerTree,u=>{if("byId"in e&&u.id!==e.byId||Q(u.type)||s&&u.type!==C.STRING)return;let c=Z(u.data,u.type,n,o);i.push(c)}),i.length!==0)return i.length===1?i[0]:i}var I=class{constructor(e,r=!1){this.response=e;this.debug=r}getValues(e=!1,r={}){return ee(this.response,e,r)}getValueByParamName(e,r){return k(this.response,{byName:e},r)}getValueByParamId(e,r){return k(this.response,{byId:e},r)}async extractMeshesFromResponse(e){let r={debug:this.debug,...e},n;try{({getThreeMeshesFromComputeResponse:n}=await Promise.resolve().then(() => _interopRequireWildcard(require("./visualization.cjs"))))}catch(o){throw new (0, _chunkXULONXVPcjs.d)("Failed to load three.js visualization module. Ensure three.js is installed as a peer dependency.",_chunkXULONXVPcjs.c.INVALID_STATE,{context:{originalError:o instanceof Error?o.message:String(o)}})}return n(this.response,r)}getFileData(){return te(this.response)}getAndDownloadFiles(e,r){let n=this.getFileData();P(n,e,r)}};function V(t,e){e||typeof window<"u"&&_chunkXULONXVPcjs.e.call(void 0, ).warn(`Warning: ${t} is running on the client side. For better performance and security, consider running this on the server side.`)}async function x(t,e,r){r.debug&&V("solveGrasshopperDefinition",r.suppressClientSideWarning);let n=B(e,t);he(n,r);let o=await _chunkXULONXVPcjs.h.call(void 0, "grasshopper",n,r);if("pointer"in o){let{pointer:s,...a}=o;return a}return o}function B(t,e){let r={algo:null,pointer:null,values:e};return t instanceof Uint8Array?r.algo=_chunk2NFN5ERTcjs.d.call(void 0, t):/^https?:\/\//i.test(t)?r.pointer=t:_chunk2NFN5ERTcjs.b.call(void 0, t)?r.algo=t:r.algo=_chunk2NFN5ERTcjs.a.call(void 0, t),r}function he(t,e){e.cachesolve!=null&&(t.cachesolve=e.cachesolve),e.modelunits!=null&&(t.modelunits=e.modelunits),e.angletolerance!=null&&(t.angletolerance=e.angletolerance),e.absolutetolerance!=null&&(t.absolutetolerance=e.absolutetolerance),e.dataversion!=null&&(t.dataversion=e.dataversion)}function re(t){if(typeof t.default!="object"||t.default===null)return;if(!("innerTree"in t.default)){_chunkXULONXVPcjs.e.call(void 0, ).warn("Unexpected structure in input.default:",t.default),t.default=null;return}let e=t.default.innerTree;if(Object.keys(e).length===0){t.default=void 0;return}if(t.treeAccess||t.atMost&&t.atMost>1){let n={};for(let[o,s]of Object.entries(e))n[o]=s.map(a=>{if(typeof a.data=="string"){if(a.type==="System.Double"||a.type==="System.Int32"){let i=Number(a.data);return Number.isNaN(i)?a.data:i}if(a.type==="System.Boolean")return a.data.toLowerCase()==="true";if(a.type.startsWith("Rhino.Geometry")||a.type==="System.String")try{return JSON.parse(a.data)}catch (e5){return a.data}}return a.data});t.default=n;return}let r=[];for(let n of Object.values(e))Array.isArray(n)&&n.forEach(o=>{o&&typeof o=="object"&&"data"in o&&r.push(o.data)});r.length===0?t.default=void 0:r.length===1?t.default=r[0]:t.default=r}function O(t,e){let{transform:r,setUndefinedOnEmpty:n=!0}=e;if(!(t.default===void 0||t.default===null))if(Array.isArray(t.default)){let o=t.default.map(r).filter(s=>s!==null);t.default=o.length>0?o:void 0}else{let o=r(t.default);o!==null?t.default=o:n&&(t.default=void 0)}}function ye(){return t=>{if(typeof t=="number")return t;if(typeof t=="string"){let e=Number(t.trim());return Number.isNaN(e)?null:e}return null}}function ge(){return t=>{if(typeof t=="boolean")return t;if(typeof t=="string"){let e=t.toLowerCase();if(e==="true")return!0;if(e==="false")return!1;throw new Error(`Invalid boolean string: "${t}"`)}return null}}function be(){return t=>typeof t=="string"?t.startsWith('"')&&t.endsWith('"')||t.startsWith('"')?t.slice(1,-1):t:null}function Te(){return t=>{if(typeof t=="string"){let e=t.trim();return e.startsWith('"')&&e.endsWith('"')&&(e=e.slice(1,-1).trim()),e}return null}}function xe(t){O(t,{transform:Te(),setUndefinedOnEmpty:!1})}function Se(t="unknown"){return e=>{if(typeof e=="object"&&e!==null)return e;if(typeof e=="string"&&e.trim()!=="")try{let r=JSON.parse(e);return typeof r=="object"&&r!==null?r:(_chunkXULONXVPcjs.e.call(void 0, ).warn(`Parsed value for input ${t} is not an object`),null)}catch(r){return _chunkXULONXVPcjs.e.call(void 0, ).warn(`Failed to parse object value "${e}" for input ${t}`,r),null}return null}}function ne(t,e,r){let n=Number(t.toFixed(e));return Math.abs(t-n)<r?n:t}function Ce(t,e=1e-8){if(!Number.isFinite(t)||t===0)return .1;let r=Math.abs(t);if(r>=1){let y=String(t).split(".")[1];if(y&&y.length>0){let g=Math.min(y.length,12),b=Math.pow(10,-g),U=Number(b.toFixed(g));return Math.abs(U-b)<e?U:b}return 1}let n=String(t),o=n.toLowerCase().match(/e(-?\d+)/);if(o){let G=Number(o[1]);if(G<0||n.toLowerCase().includes("e-")){let y=Math.abs(G),g=Math.pow(10,-y),b=Number(g.toFixed(y));return Math.abs(b-g)<e?b:g}return .1}let s=12,i=r.toFixed(s).replace(/0+$/,""),u=Math.min((i.split(".")[1]||"").length,s);if(u===0)return .1;let c=Math.pow(10,-u),d=Number(c.toFixed(u));return Math.abs(d-c)<e?d:c}function oe(t,e=1e-8){let r=t.paramType==="Integer";if(O(t,{transform:ye()}),r){Array.isArray(t.default)?t.default=t.default.map(s=>typeof s=="number"?Math.round(s):s):typeof t.default=="number"&&(t.default=Math.round(t.default)),t.stepSize=1;return}let n=Array.isArray(t.default)?t.default[0]:t.default,o;if(typeof n=="number"&&Number.isFinite(n)&&n!==0?o=n:typeof t.minimum=="number"&&Number.isFinite(t.minimum)&&t.minimum!==0?o=t.minimum:typeof t.maximum=="number"&&Number.isFinite(t.maximum)&&t.maximum!==0&&(o=t.maximum),o!==void 0?t.stepSize=Ce(o,e):t.stepSize=.1,typeof t.stepSize=="number"){let s=0,a=String(t.stepSize),i=a.toLowerCase().match(/e(-?\d+)/);if(i?s=Math.abs(Number(i[1])):s=_nullishCoalesce(_optionalChain([a, 'access', _19 => _19.split, 'call', _20 => _20("."), 'access', _21 => _21[1], 'optionalAccess', _22 => _22.length]), () => (0)),s===0&&typeof n=="number"&&n!==0&&Math.abs(n)<1){let u=Math.ceil(-Math.log10(Math.abs(n)));Number.isFinite(u)&&u>0&&(s=u)}s=Math.min(Math.max(s,0),12),Array.isArray(t.default)?t.default=t.default.map(u=>typeof u=="number"?ne(u,s,e):u):typeof t.default=="number"&&(t.default=ne(t.default,s,e))}}function Ie(t){try{O(t,{transform:ge(),setUndefinedOnEmpty:!1})}catch(e){throw e instanceof Error?new (0, _chunkXULONXVPcjs.d)(e.message):e}}function De(t){O(t,{transform:be(),setUndefinedOnEmpty:!1})}function se(t){O(t,{transform:Se(t.nickname||"unnamed"),setUndefinedOnEmpty:!0})}function ve(t){if(!t.values||typeof t.values!="object"||Object.keys(t.values).length===0)throw _chunkXULONXVPcjs.d.missingValues(t.nickname||"unnamed","ValueList");if(t.default!==void 0&&t.default!==null){let e=String(t.default).toLowerCase();Object.keys(t.values).some(n=>n.toLowerCase()===e)||_chunkXULONXVPcjs.e.call(void 0, ).warn(`ValueList input "${t.nickname||"unnamed"}" default value "${t.default}" is not in available values`)}}var ae={Number:oe,Integer:oe,Boolean:Ie,Text:De,ValueList:ve,Geometry:se,File:se,Color:xe};function Re(t,e){let r=(_nullishCoalesce(t.atMost, () => (1)))>1;switch(t.paramType){case"Number":case"Integer":return{...e,paramType:t.paramType,minimum:t.minimum,maximum:t.maximum,atLeast:t.atLeast,atMost:t.atMost,default:r?[0]:0};case"Boolean":return{...e,paramType:"Boolean",default:r?[!1]:!1};case"Text":return{...e,paramType:"Text",default:r?[""]:""};case"ValueList":return{...e,paramType:"ValueList",values:_nullishCoalesce(t.values, () => ({})),default:r?[t.default]:t.default};case"File":return{...e,paramType:"File",default:r?[null]:null};case"Color":return{...e,paramType:"Color",default:r?["0, 0, 0"]:"0, 0, 0"};default:return{...e,paramType:"Geometry",default:r?[null]:null}}}function F(t){let e={description:t.description,name:t.name,nickname:t.nickname,treeAccess:t.treeAccess,groupName:_nullishCoalesce(t.groupName, () => ("")),id:t.id};try{re(t);let r=ae[t.paramType];if(!r)throw _chunkXULONXVPcjs.d.unknownParamType(t.paramType,t.name);switch(r(t),t.paramType){case"Number":case"Integer":return{...e,paramType:t.paramType,minimum:t.minimum,maximum:t.maximum,atLeast:t.atLeast,atMost:t.atMost,stepSize:t.stepSize,default:t.default};case"Boolean":return{...e,paramType:"Boolean",default:t.default};case"Text":return{...e,paramType:"Text",default:t.default};case"ValueList":return{...e,paramType:"ValueList",values:t.values,default:t.default};case"Geometry":return{...e,paramType:t.paramType,default:t.default};case"File":return{...e,paramType:t.paramType,acceptedFormats:t.acceptedFormats,default:t.default};case"Color":return{...e,paramType:"Color",default:t.default};default:throw _chunkXULONXVPcjs.d.unknownParamType(t.paramType,t.name)}}catch(r){if(r instanceof _chunkXULONXVPcjs.d)return _chunkXULONXVPcjs.e.call(void 0, ).error(`Validation error for input ${t.name||"unknown"}:`,r.message),Re(t,e);throw new (0, _chunkXULONXVPcjs.d)(r instanceof Error?r.message:String(r),"VALIDATION_ERROR",{context:{paramName:t.name,paramType:t.paramType},originalError:r instanceof Error?r:new Error(String(r))})}}function D(t){return t.map(e=>F(e))}async function S(t,e){let r=B(t,[]),n={};if(r.algo&&(n.algo=r.algo),r.pointer&&(n.pointer=r.pointer),!n.algo&&!n.pointer)throw new (0, _chunkXULONXVPcjs.d)("Definition must resolve to either a URL pointer or base64 algo",_chunkXULONXVPcjs.c.INVALID_INPUT,{context:{definition:t}});let o=await _chunkXULONXVPcjs.h.call(void 0, "io",n,e);if(!o||typeof o!="object")throw new (0, _chunkXULONXVPcjs.d)("Invalid IO response structure",_chunkXULONXVPcjs.c.INVALID_INPUT,{context:{response:o,definition:t}});let s=_chunkXULONXVPcjs.k.call(void 0, o,{deep:!0});return{inputs:s.inputs,outputs:s.outputs}}async function R(t,e){V("fetchParsedDefinitionIO",e.suppressClientSideWarning);let{inputs:r,outputs:n}=await S(t,e);return{inputs:D(r),outputs:n}}var w=class t{constructor(e){_chunkXULONXVPcjs.b.call(void 0, this,"innerTree");_chunkXULONXVPcjs.b.call(void 0, this,"paramName");this.paramName=e,this.innerTree={}}append(e,r){let n=t.formatPathString(e);this.innerTree[n]||(this.innerTree[n]=[]);let o=r.map(s=>({data:t.serializeValue(s)}));return this.innerTree[n].push(...o),this}appendSingle(e,r){return this.append(e,[r])}fromDataTreeDefault(e){this.innerTree={};for(let[r,n]of Object.entries(e)){if(!Array.isArray(n))continue;let o=t.parsePathString(r);this.append(o,n)}return this}appendFlat(e){let r=Array.isArray(e)?e:[e];return this.append([0],r)}flatten(){let e=[];for(let r of Object.values(this.innerTree))if(Array.isArray(r))for(let n of r)e.push(t.deserializeValue(n.data));return e}getPaths(){return Object.keys(this.innerTree)}getPath(e){let r=t.formatPathString(e),n=this.innerTree[r];if(n)return n.map(o=>t.deserializeValue(o.data))}toComputeFormat(){return{ParamName:this.paramName,InnerTree:this.innerTree}}getInnerTree(){return this.innerTree}getParamName(){return this.paramName}static fromInputParams(e){return e.filter(r=>t.hasValidValue(r.default)).map(r=>{let n=new t(r.nickname||"unnamed"),o=r.default;if(r.treeAccess&&t.isDataTreeStructure(o))n.fromDataTreeDefault(o),t.isNumericInput(r)&&n.applyNumericConstraints(r.minimum,r.maximum,r.nickname||"unnamed");else{let s=Array.isArray(o)?o:[o],a=t.processValues(s,r);n.appendFlat(a)}return n.toComputeFormat()})}static fromInputParam(e){return t.hasValidValue(e.default)?t.fromInputParams([e])[0]:void 0}static replaceTreeValue(e,r,n){if(e.length>0&&e[0]instanceof t){let s=e,a=s.findIndex(u=>u.getParamName()===r),i=new t(r);return typeof n=="object"&&n!==null&&!Array.isArray(n)&&t.isDataTreeStructure(n)?i.fromDataTreeDefault(n):(Array.isArray(n),i.appendFlat(n)),a!==-1?s[a]=i:s.push(i),s}else{let s=e,a=s.findIndex(c=>c.ParamName===r),i=new t(r);typeof n=="object"&&n!==null&&!Array.isArray(n)&&t.isDataTreeStructure(n)?i.fromDataTreeDefault(n):(Array.isArray(n),i.appendFlat(n));let u=i.toComputeFormat();return a!==-1?s[a]=u:s.push(u),s}}static getTreeValue(e,r){if(e.length>0&&e[0]instanceof t){let s=e.find(i=>i.getParamName()===r);if(!s)return null;let a=s.flatten();return a.length===0?null:a.length===1?a[0]:a}else{let s=e.find(c=>c.ParamName===r);if(!s)return null;let a=s.InnerTree;if(!a)return null;let i=Object.keys(a)[0];if(!i)return null;let u=a[i];if(Array.isArray(u)){if(u.length===1){let c=_optionalChain([u, 'access', _23 => _23[0], 'optionalAccess', _24 => _24.data]);return c!==void 0?t.deserializeValue(c):null}return u.map(c=>_optionalChain([c, 'optionalAccess', _25 => _25.data])!==void 0?t.deserializeValue(c.data):null).filter(c=>c!==null)}return _optionalChain([u, 'optionalAccess', _26 => _26.data])!==void 0?t.deserializeValue(u.data):u}}static parsePathString(e){let r=e.match(/^\{([\d;]*)\}$/);return r?r[1]===""?[]:r[1].split(";").map(Number):(_chunkXULONXVPcjs.e.call(void 0, ).warn(`Invalid TreeBuilder path format: ${e}, using [0]`),[0])}static formatPathString(e){return`{${e.join(";")}}`}applyNumericConstraints(e,r,n){for(let o of Object.values(this.innerTree))if(Array.isArray(o))for(let s of o){let a=t.deserializeValue(s.data);if(typeof a=="number"){let i=t.clampValue(a,e,r,n);s.data=t.serializeValue(i)}}}static serializeValue(e){return typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:typeof e=="object"&&e!==null?JSON.stringify(e):String(e)}static deserializeValue(e){if(typeof e=="boolean"||typeof e=="number"||typeof e!="string")return e;if(e.startsWith("{")||e.startsWith("["))try{return JSON.parse(e)}catch (e6){return e}return isNaN(Number(e))?e==="true"?!0:e==="false"?!1:e:Number(e)}static hasValidValue(e){return e==null?!1:typeof e=="string"?!0:!(Array.isArray(e)&&e.length===0||typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===0)}static isDataTreeStructure(e){return typeof e!="object"||e===null||Array.isArray(e)?!1:Object.entries(e).every(([r,n])=>typeof r=="string"&&/^\{[\d;]+\}$/.test(r)&&Array.isArray(n))}static isNumericInput(e){return e.paramType==="Number"||e.paramType==="Integer"}static processValues(e,r){return e.map(n=>t.isNumericInput(r)&&typeof n=="number"?t.clampValue(n,r.minimum,r.maximum,r.nickname||"unnamed"):n).filter(n=>n!=null)}static clampValue(e,r,n,o){let s=e;return r!=null&&s<r&&(_chunkXULONXVPcjs.e.call(void 0, ).warn(`${o}: ${e} below min ${r}, clamping`),s=r),n!=null&&s>n&&(_chunkXULONXVPcjs.e.call(void 0, ).warn(`${o}: ${e} above max ${n}, clamping`),s=n),s}};exports.a = v; exports.b = h; exports.c = T; exports.d = M; exports.e = P; exports.f = I; exports.g = x; exports.h = F; exports.i = D; exports.j = S; exports.k = R; exports.l = w;
2
+ //# sourceMappingURL=chunk-JSS6OQML.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/chunk-FRSLCR7G.cjs","../src/features/grasshopper/scheduler/stable-hash.ts"],"names":["stableStringify","value","seen","stringify","v","sample","k"],"mappings":"AAAA,2/BAA6D,wDAAmF,SCWhIA,CAAAA,CAAgBC,CAAAA,CAAwB,CACvD,IAAMC,CAAAA,CAAO,IAAI,OAAA,CAEXC,CAAAA,CAAaC,CAAAA,EAAuB,CACzC,EAAA,CAAIA,CAAAA,EAAM,IAAA,CAAyB,OAAO,IAAA,CAAK,SAAA,CAAUA,CAAC,CAAA,CAC1D,EAAA,CAAI,OAAOA,CAAAA,EAAM,QAAA,CAChB,OAAO,MAAA,CAAO,QAAA,CAASA,CAAC,CAAA,CAAI,MAAA,CAAOA,CAAC,CAAA,CAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,CAE5D,EAAA,CAAI,OAAOA,CAAAA,EAAM,QAAA,EAAY,OAAOA,CAAAA,EAAM,SAAA,CAAW,OAAO,IAAA,CAAK,SAAA,CAAUA,CAAC,CAAA,CAC5E,EAAA,CAAI,OAAOA,CAAAA,EAAM,QAAA,CAAU,OAAO,IAAA,CAAK,SAAA,CAAUA,CAAAA,CAAE,QAAA,CAAS,CAAC,CAAA,CAC7D,EAAA,CAAIA,EAAAA,WAAa,UAAA,CAAY,CAE5B,IAAMC,CAAAA,CAASD,CAAAA,CAAE,MAAA,CAAS,EAAA,CAAK,KAAA,CAAM,IAAA,CAAKA,CAAAA,CAAE,KAAA,CAAM,CAAA,CAAG,EAAE,CAAC,CAAA,CAAE,MAAA,CAAO,KAAA,CAAM,IAAA,CAAKA,CAAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAI,KAAA,CAAM,IAAA,CAAKA,CAAC,CAAA,CACzG,OAAO,IAAA,CAAK,SAAA,CAAU,CAAE,IAAA,CAAM,CAAA,CAAA,CAAM,GAAA,CAAKA,CAAAA,CAAE,MAAA,CAAQ,MAAA,CAAAC,CAAO,CAAC,CAC5D,CACA,OAAI,KAAA,CAAM,OAAA,CAAQD,CAAC,CAAA,CACX,CAAA,CAAA,EAAIA,CAAAA,CAAE,GAAA,CAAID,CAAS,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,CAAA,CAElC,OAAOC,CAAAA,EAAM,QAAA,CACZF,CAAAA,CAAK,GAAA,CAAIE,CAAW,CAAA,CAAU,IAAA,CAAK,SAAA,CAAU,YAAY,CAAA,CAAA,CAC7DF,CAAAA,CAAK,GAAA,CAAIE,CAAW,CAAA,CAGb,CAAA,CAAA,EAFM,MAAA,CAAO,IAAA,CAAKA,CAAW,CAAA,CAAE,IAAA,CAAK,CAAA,CACxB,GAAA,CAAKE,CAAAA,EAAM,CAAA,EAAA","file":"/home/runner/work/selva-compute/selva-compute/dist/chunk-FRSLCR7G.cjs","sourcesContent":[null,"/**\n * Stable hashing helpers for solve dedupe / cache keys.\n *\n * @internal\n */\n\n/**\n * Deterministic JSON stringify — keys are sorted at every object level so\n * `{a:1,b:2}` and `{b:2,a:1}` produce the same string. Handles circular\n * references safely (replaces with a sentinel) and non-finite numbers.\n */\nexport function stableStringify(value: unknown): string {\n\tconst seen = new WeakSet<object>();\n\n\tconst stringify = (v: unknown): string => {\n\t\tif (v === null || v === undefined) return JSON.stringify(v);\n\t\tif (typeof v === 'number') {\n\t\t\treturn Number.isFinite(v) ? String(v) : JSON.stringify(null);\n\t\t}\n\t\tif (typeof v === 'string' || typeof v === 'boolean') return JSON.stringify(v);\n\t\tif (typeof v === 'bigint') return JSON.stringify(v.toString());\n\t\tif (v instanceof Uint8Array) {\n\t\t\t// Hash bytes by length + a sample to avoid stringifying multi-MB buffers fully\n\t\t\tconst sample = v.length > 64 ? Array.from(v.slice(0, 32)).concat(Array.from(v.slice(-32))) : Array.from(v);\n\t\t\treturn JSON.stringify({ __u8: true, len: v.length, sample });\n\t\t}\n\t\tif (Array.isArray(v)) {\n\t\t\treturn `[${v.map(stringify).join(',')}]`;\n\t\t}\n\t\tif (typeof v === 'object') {\n\t\t\tif (seen.has(v as object)) return JSON.stringify('[Circular]');\n\t\t\tseen.add(v as object);\n\t\t\tconst keys = Object.keys(v as object).sort();\n\t\t\tconst parts = keys.map((k) => `${JSON.stringify(k)}:${stringify((v as any)[k])}`);\n\t\t\treturn `{${parts.join(',')}}`;\n\t\t}\n\t\t// Fallback for functions, symbols, etc.\n\t\treturn JSON.stringify(null);\n\t};\n\n\treturn stringify(value);\n}\n\n/**\n * 32-bit FNV-1a hash. Fast, no deps, good enough for dedupe/cache keys.\n * Returns an unsigned hex string.\n */\nexport function fnv1a(input: string): string {\n\tlet hash = 0x811c9dc5;\n\tfor (let i = 0; i < input.length; i++) {\n\t\thash ^= input.charCodeAt(i);\n\t\thash = (hash + ((hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24))) >>> 0;\n\t}\n\treturn hash.toString(16).padStart(8, '0');\n}\n\n/**\n * Hash a (definition, dataTree) pair into a short stable key.\n * For Uint8Array definitions we use length + endpoint bytes rather than the\n * full content to keep hashing cheap.\n */\nexport function hashSolveInput(definition: string | Uint8Array, dataTree: unknown): string {\n\tconst defKey =\n\t\ttypeof definition === 'string'\n\t\t\t? definition\n\t\t\t: stableStringify({ __u8: true, len: definition.length });\n\treturn fnv1a(`${defKey}|${stableStringify(dataTree)}`);\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/chunk-JSS6OQML.cjs","../src/features/grasshopper/scheduler/stable-hash.ts"],"names":["stableStringify","value","seen","stringify","v","sample","k"],"mappings":"AAAA,2/BAA6D,wDAAmF,SCWhIA,CAAAA,CAAgBC,CAAAA,CAAwB,CACvD,IAAMC,CAAAA,CAAO,IAAI,OAAA,CAEXC,CAAAA,CAAaC,CAAAA,EAAuB,CACzC,EAAA,CAAIA,CAAAA,EAAM,IAAA,CAAyB,OAAO,IAAA,CAAK,SAAA,CAAUA,CAAC,CAAA,CAC1D,EAAA,CAAI,OAAOA,CAAAA,EAAM,QAAA,CAChB,OAAO,MAAA,CAAO,QAAA,CAASA,CAAC,CAAA,CAAI,MAAA,CAAOA,CAAC,CAAA,CAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,CAE5D,EAAA,CAAI,OAAOA,CAAAA,EAAM,QAAA,EAAY,OAAOA,CAAAA,EAAM,SAAA,CAAW,OAAO,IAAA,CAAK,SAAA,CAAUA,CAAC,CAAA,CAC5E,EAAA,CAAI,OAAOA,CAAAA,EAAM,QAAA,CAAU,OAAO,IAAA,CAAK,SAAA,CAAUA,CAAAA,CAAE,QAAA,CAAS,CAAC,CAAA,CAC7D,EAAA,CAAIA,EAAAA,WAAa,UAAA,CAAY,CAE5B,IAAMC,CAAAA,CAASD,CAAAA,CAAE,MAAA,CAAS,EAAA,CAAK,KAAA,CAAM,IAAA,CAAKA,CAAAA,CAAE,KAAA,CAAM,CAAA,CAAG,EAAE,CAAC,CAAA,CAAE,MAAA,CAAO,KAAA,CAAM,IAAA,CAAKA,CAAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAI,KAAA,CAAM,IAAA,CAAKA,CAAC,CAAA,CACzG,OAAO,IAAA,CAAK,SAAA,CAAU,CAAE,IAAA,CAAM,CAAA,CAAA,CAAM,GAAA,CAAKA,CAAAA,CAAE,MAAA,CAAQ,MAAA,CAAAC,CAAO,CAAC,CAC5D,CACA,OAAI,KAAA,CAAM,OAAA,CAAQD,CAAC,CAAA,CACX,CAAA,CAAA,EAAIA,CAAAA,CAAE,GAAA,CAAID,CAAS,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,CAAA,CAElC,OAAOC,CAAAA,EAAM,QAAA,CACZF,CAAAA,CAAK,GAAA,CAAIE,CAAW,CAAA,CAAU,IAAA,CAAK,SAAA,CAAU,YAAY,CAAA,CAAA,CAC7DF,CAAAA,CAAK,GAAA,CAAIE,CAAW,CAAA,CAGb,CAAA,CAAA,EAFM,MAAA,CAAO,IAAA,CAAKA,CAAW,CAAA,CAAE,IAAA,CAAK,CAAA,CACxB,GAAA,CAAKE,CAAAA,EAAM,CAAA,EAAA","file":"/home/runner/work/selva-compute/selva-compute/dist/chunk-JSS6OQML.cjs","sourcesContent":[null,"/**\n * Stable hashing helpers for solve dedupe / cache keys.\n *\n * @internal\n */\n\n/**\n * Deterministic JSON stringify — keys are sorted at every object level so\n * `{a:1,b:2}` and `{b:2,a:1}` produce the same string. Handles circular\n * references safely (replaces with a sentinel) and non-finite numbers.\n */\nexport function stableStringify(value: unknown): string {\n\tconst seen = new WeakSet<object>();\n\n\tconst stringify = (v: unknown): string => {\n\t\tif (v === null || v === undefined) return JSON.stringify(v);\n\t\tif (typeof v === 'number') {\n\t\t\treturn Number.isFinite(v) ? String(v) : JSON.stringify(null);\n\t\t}\n\t\tif (typeof v === 'string' || typeof v === 'boolean') return JSON.stringify(v);\n\t\tif (typeof v === 'bigint') return JSON.stringify(v.toString());\n\t\tif (v instanceof Uint8Array) {\n\t\t\t// Hash bytes by length + a sample to avoid stringifying multi-MB buffers fully\n\t\t\tconst sample = v.length > 64 ? Array.from(v.slice(0, 32)).concat(Array.from(v.slice(-32))) : Array.from(v);\n\t\t\treturn JSON.stringify({ __u8: true, len: v.length, sample });\n\t\t}\n\t\tif (Array.isArray(v)) {\n\t\t\treturn `[${v.map(stringify).join(',')}]`;\n\t\t}\n\t\tif (typeof v === 'object') {\n\t\t\tif (seen.has(v as object)) return JSON.stringify('[Circular]');\n\t\t\tseen.add(v as object);\n\t\t\tconst keys = Object.keys(v as object).sort();\n\t\t\tconst parts = keys.map((k) => `${JSON.stringify(k)}:${stringify((v as any)[k])}`);\n\t\t\treturn `{${parts.join(',')}}`;\n\t\t}\n\t\t// Fallback for functions, symbols, etc.\n\t\treturn JSON.stringify(null);\n\t};\n\n\treturn stringify(value);\n}\n\n/**\n * 32-bit FNV-1a hash. Fast, no deps, good enough for dedupe/cache keys.\n * Returns an unsigned hex string.\n */\nexport function fnv1a(input: string): string {\n\tlet hash = 0x811c9dc5;\n\tfor (let i = 0; i < input.length; i++) {\n\t\thash ^= input.charCodeAt(i);\n\t\thash = (hash + ((hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24))) >>> 0;\n\t}\n\treturn hash.toString(16).padStart(8, '0');\n}\n\n/**\n * Hash a (definition, dataTree) pair into a short stable key.\n * For Uint8Array definitions we use length + endpoint bytes rather than the\n * full content to keep hashing cheap.\n */\nexport function hashSolveInput(definition: string | Uint8Array, dataTree: unknown): string {\n\tconst defKey =\n\t\ttypeof definition === 'string'\n\t\t\t? definition\n\t\t\t: stableStringify({ __u8: true, len: definition.length });\n\treturn fnv1a(`${defKey}|${stableStringify(dataTree)}`);\n}\n"]}
@@ -1,3 +1,3 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var S=Object.defineProperty;var $=(e,r,t)=>r in e?S(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var W=(e,r)=>{for(var t in r)S(e,t,{get:r[t],enumerable:!0})};var R=(e,r,t)=>$(e,typeof r!="symbol"?r+"":r,t);var a={NETWORK_ERROR:"NETWORK_ERROR",AUTH_ERROR:"AUTH_ERROR",VALIDATION_ERROR:"VALIDATION_ERROR",COMPUTATION_ERROR:"COMPUTATION_ERROR",TIMEOUT_ERROR:"TIMEOUT_ERROR",CORS_ERROR:"CORS_ERROR",UNKNOWN_ERROR:"UNKNOWN_ERROR",INVALID_STATE:"INVALID_STATE",INVALID_INPUT:"INVALID_INPUT",INVALID_CONFIG:"INVALID_CONFIG",BROWSER_ONLY:"BROWSER_ONLY",ENVIRONMENT_ERROR:"ENVIRONMENT_ERROR",ENCODING_ERROR:"ENCODING_ERROR"};var d=class e extends Error{constructor(t,n="UNKNOWN_ERROR",s){super(t);R(this,"code");R(this,"statusCode");R(this,"context");R(this,"originalError");this.name="RhinoComputeError",this.code=n,this.statusCode=_optionalChain([s, 'optionalAccess', _2 => _2.statusCode]),this.context=_optionalChain([s, 'optionalAccess', _3 => _3.context]),this.originalError=_optionalChain([s, 'optionalAccess', _4 => _4.originalError]),"cause"in Error.prototype&&Object.defineProperty(this,"cause",{value:_optionalChain([s, 'optionalAccess', _5 => _5.originalError]),enumerable:!0})}static validation(t,n,s){return new e(`Input "${t}": ${n}`,a.VALIDATION_ERROR,{context:{inputName:t,reason:n,...s}})}static missingValues(t,n,s){return new e(`Input "${t}" has no values defined${n?` (expected ${n})`:""}`,a.INVALID_INPUT,{context:{inputName:t,expectedType:n,...s}})}static invalidDefault(t,n,s,i){return new e(`ValueList input "${t}" default value "${n}" is not in available values`,a.VALIDATION_ERROR,{context:{inputName:t,defaultValue:n,availableValues:s,...i}})}static unknownParamType(t,n,s){return new e(`Unknown paramType: ${t}`,a.VALIDATION_ERROR,{context:{receivedParamType:t,paramName:n,...s}})}static invalidStructure(t,n,s){return new e(`Invalid input structure for "${t}" (expected ${n})`,a.INVALID_INPUT,{context:{inputName:t,expectedStructure:n,...s}})}};var v=class{debug(){}info(){}warn(){}error(){}},O=class{debug(r,...t){console.debug(r,...t)}info(r,...t){console.info(r,...t)}warn(r,...t){console.warn(r,...t)}error(r,...t){console.error(r,...t)}},b=new v;function p(){return b}function N(e){e===null?b=new v:"debug"in e&&"info"in e&&"warn"in e&&"error"in e?b=e:b=new O}function _(){N(new O)}var y={attempts:0,baseDelayMs:500,maxDelayMs:3e4,retryOn429:!0},I=new Set([502,503,504]);function k(e){return e?{attempts:_nullishCoalesce(e.attempts, () => (y.attempts)),baseDelayMs:_nullishCoalesce(e.baseDelayMs, () => (y.baseDelayMs)),maxDelayMs:_nullishCoalesce(e.maxDelayMs, () => (y.maxDelayMs)),retryOn429:_nullishCoalesce(e.retryOn429, () => (y.retryOn429))}:y}function M(e){if(!e)return null;let r=Number(e);if(Number.isFinite(r)&&r>=0)return r*1e3;let t=Date.parse(e);if(Number.isFinite(t)){let n=t-Date.now();return n>0?n:0}return null}function w(e,r){let t=r.baseDelayMs*Math.pow(2,e),n=Math.random()*r.baseDelayMs;return Math.min(t+n,r.maxDelayMs)}function x(e,r){return new Promise((t,n)=>{if(_optionalChain([r, 'optionalAccess', _6 => _6.aborted])){n(new DOMException("Aborted","AbortError"));return}let s=setTimeout(()=>{_optionalChain([r, 'optionalAccess', _7 => _7.removeEventListener, 'call', _8 => _8("abort",i)]),t()},e),i=()=>{clearTimeout(s),n(new DOMException("Aborted","AbortError"))};_optionalChain([r, 'optionalAccess', _9 => _9.addEventListener, 'call', _10 => _10("abort",i,{once:!0})])})}function L(e,r,t,n,s,i){let{status:c,statusText:o}=e,l={url:r,requestId:t,method:"POST",requestSize:n,serverUrl:s},u=i?` \u2014 ${i.slice(0,200)}`:"",m={401:{message:`HTTP ${c}: ${o}${u}`,code:a.AUTH_ERROR},403:{message:`HTTP ${c}: ${o}${u}`,code:a.AUTH_ERROR},404:{message:`Endpoint not found: ${r}`,code:a.NETWORK_ERROR},413:{message:`Request too large: ${(n/1024).toFixed(2)}KB`,code:a.VALIDATION_ERROR},429:{message:"Rate limit exceeded",code:a.NETWORK_ERROR},500:{message:`Server error: ${i||o}`,code:a.COMPUTATION_ERROR},502:{message:`Service unavailable: ${o}`,code:a.NETWORK_ERROR},503:{message:`Service unavailable: ${o}`,code:a.NETWORK_ERROR},504:{message:`Service unavailable: ${o}`,code:a.NETWORK_ERROR}}[c]||{message:`HTTP ${c}: ${o}`,code:a.UNKNOWN_ERROR};throw new d(m.message,m.code,{statusCode:c,context:l})}function D(e,r){let t=r.replace(/\/+$/,""),n=e.replace(/^\/+/,"");return`${t}/${n}`}function U(e){try{let r=new URL(e).host;return/^(localhost|127\.0\.0\.1|::1)(:\d+)?$/i.test(r)}catch (e2){return/(localhost|127\.0\.0\.1)/i.test(e)}}function q(e,r){let t={"X-Request-ID":e,"Content-Type":"application/json",...r.authToken&&{Authorization:r.authToken},...r.apiKey&&{RhinoComputeKey:r.apiKey}};return!r.apiKey&&!U(r.serverUrl)&&p().warn(`\u26A0\uFE0F [Rhino Compute] Request [${e}] targets remote server (${r.serverUrl}) but no API key is configured. Requests may fail or be rate-limited.`),t}function K(){return`${Date.now()}-${Math.random().toString(36).substring(2,11)}`}function f(e,r){r&&p().debug(e)}function P(e,r){let t=[],n=()=>{};if(e&&t.push(e),r&&r>0)if(typeof AbortSignal<"u"&&typeof AbortSignal.timeout=="function")t.push(AbortSignal.timeout(r));else{let o=new AbortController,l=setTimeout(()=>o.abort(),r);n=()=>clearTimeout(l),t.push(o.signal)}if(t.length===0)return{signal:void 0,cleanup:n};if(t.length===1)return{signal:t[0],cleanup:n};if(typeof AbortSignal<"u"&&typeof AbortSignal.any=="function")return{signal:AbortSignal.any(t),cleanup:n};let s=new AbortController,i=()=>s.abort();for(let o of t){if(o.aborted){s.abort();break}o.addEventListener("abort",i,{once:!0})}let c=n;return n=()=>{c();for(let o of t)o.removeEventListener("abort",i)},{signal:s.signal,cleanup:n}}async function F(e,r,t,n,s,i,c){let o=Math.round(performance.now()-i);if(!e.ok){let l=await e.text();if(c&&(f(`\u274C Request [${t}] failed with HTTP ${e.status} in ${o}ms`,!0),f(` URL: ${r}`,!0),f(` Status: ${e.status} ${e.statusText}`,!0),l&&f(` Response body: ${l.substring(0,500)}${l.length>500?"...":""}`,!0)),e.status===500)try{let u=JSON.parse(l);if(_optionalChain([u, 'optionalAccess', _11 => _11.values])&&(u.errors||u.warnings))return c&&(f(`\u26A0\uFE0F Request [${t}] completed with Grasshopper errors in ${o}ms`,!0),_optionalChain([u, 'access', _12 => _12.errors, 'optionalAccess', _13 => _13.length])>0&&f(` Errors: ${JSON.stringify(u.errors,null,2)}`,!0),_optionalChain([u, 'access', _14 => _14.warnings, 'optionalAccess', _15 => _15.length])>0&&f(` Warnings: ${JSON.stringify(u.warnings,null,2)}`,!0)),u;_optionalChain([u, 'optionalAccess', _16 => _16.Message])?l=`${u.ExceptionType?u.ExceptionType+": ":""}${u.Message}
2
- ${u.StackTrace||""}`:_optionalChain([u, 'optionalAccess', _17 => _17.error])&&(l=typeof u.error=="string"?u.error:JSON.stringify(u.error,null,2))}catch(u){c&&f(` Failed to parse error body as JSON: ${u}`,!0)}L(e,r,t,n,s,l)}f(`\u2705 Request [${t}] completed in ${o}ms`,c);try{return await e.json()}catch(l){throw new d("Failed to parse JSON response",a.NETWORK_ERROR,{statusCode:e.status,context:{url:r,requestId:t},originalError:l instanceof Error?l:new Error(String(l))})}}async function H(e,r,t,n){let{signal:s,cleanup:i}=P(e.config.signal,e.config.timeoutMs),c=performance.now();try{let o=await fetch(e.fullUrl,{method:"POST",body:e.body,headers:e.headers,signal:s});if((I.has(o.status)||r.retryOn429&&o.status===429)&&t<n-1){let m=_nullishCoalesce(M(o.headers.get("Retry-After")), () => (w(t,r)));return await o.text().catch(()=>{}),{ok:!1,retry:!0,delayMs:m,cause:new d(`HTTP ${o.status} ${o.statusText} (will retry)`,a.NETWORK_ERROR,{statusCode:o.status,context:{requestId:e.requestId}})}}return{ok:!0,value:await F(o,e.fullUrl,e.requestId,e.requestSize,e.config.serverUrl,c,e.config.debug)}}catch(o){if(o instanceof Error&&(o.name==="AbortError"||o.name==="TimeoutError")){if(_optionalChain([e, 'access', _18 => _18.config, 'access', _19 => _19.signal, 'optionalAccess', _20 => _20.aborted])===!0)return{ok:!1,retry:!1,cause:new d("Request aborted by caller",a.UNKNOWN_ERROR,{context:{endpoint:e.endpoint,requestId:e.requestId,requestSize:e.requestSize},originalError:o})};let u=new d(`Request timed out after ${e.config.timeoutMs}ms`,a.TIMEOUT_ERROR,{context:{serverUrl:e.config.serverUrl,timeoutMs:e.config.timeoutMs,url:e.fullUrl,requestId:e.requestId,endpoint:e.endpoint,requestSize:e.requestSize}});return t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:u}:{ok:!1,retry:!1,cause:u}}if(o instanceof TypeError){let l=new d(`Network error: ${o.message}`,a.NETWORK_ERROR,{context:{serverUrl:e.config.serverUrl,url:e.fullUrl,requestId:e.requestId,endpoint:e.endpoint,requestSize:e.requestSize},originalError:o});return t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:l}:{ok:!1,retry:!1,cause:l}}if(o instanceof d){let l=o.statusCode;return l!==void 0&&(I.has(l)||r.retryOn429&&l===429)&&t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:o}:{ok:!1,retry:!1,cause:o}}return{ok:!1,retry:!1,cause:new d(o instanceof Error?o.message:String(o),a.UNKNOWN_ERROR,{context:{endpoint:e.endpoint,requestId:e.requestId},originalError:o instanceof Error?o:new Error(String(o))})}}finally{i()}}async function V(e,r,t){let n=K(),s=JSON.stringify(r),i=s.length,c=D(e,t.serverUrl),o=q(n,t),l=k(t.retry),u=l.attempts+1;if(t.debug){let h=(i/1024).toFixed(2),g=i>1e5?"\u26A0\uFE0F":"\u{1F680}";f(`${g} Starting compute request [${n}]: ${e} (${h}KB)`,!0)}let T={endpoint:e,body:s,requestSize:i,fullUrl:c,requestId:n,headers:o,config:t},m=null;for(let h=0;h<u;h++){let g=await H(T,l,h,u);if(g.ok)return g.value;if(!g.retry)throw g.cause;m=g.cause,t.debug&&f(`\u{1F501} Request [${n}] retrying after ${g.delayMs}ms (attempt ${h+2}/${u}): ${g.cause.message}`,!0);try{await x(g.delayMs,t.signal)}catch (e3){throw new d("Request aborted by caller",a.UNKNOWN_ERROR,{context:{endpoint:e,requestId:n,requestSize:i},originalError:m})}}throw _nullishCoalesce(m, () => (new d("Unknown error after retries",a.UNKNOWN_ERROR,{context:{endpoint:e,requestId:n,requestSize:i}})))}var E=class{constructor(r,t){R(this,"serverUrl");R(this,"apiKey");R(this,"disposed",!1);R(this,"activeMonitors",new Set);R(this,"activeTimeouts",new Set);if(!_optionalChain([r, 'optionalAccess', _21 => _21.trim, 'call', _22 => _22()]))throw new d("serverUrl is required",a.INVALID_CONFIG,{context:{serverUrl:r}});if(!r.match(/^https?:\/\//))throw new d(`Invalid serverUrl: "${r}". Must start with "http://" or "https://". For example: "http://localhost:5000" or "https://example.com"`,a.INVALID_CONFIG,{context:{serverUrl:r}});try{new URL(r)}catch(n){throw new d(`Invalid serverUrl: "${r}". Must be a valid URL. Received error: ${n instanceof Error?n.message:String(n)}`,a.INVALID_CONFIG,{context:{serverUrl:r},originalError:n instanceof Error?n:void 0})}this.apiKey=t,this.serverUrl=r.replace(/\/+$/,"")}buildHeaders(){let r={"Content-Type":"application/json"};return this.apiKey&&(r.RhinoComputeKey=this.apiKey),r}async isServerOnline(){this.ensureNotDisposed();let r=`${this.serverUrl}/healthcheck`,t={headers:this.buildHeaders(),method:"GET"};try{return(await fetch(r,t)).ok}catch(n){return p().debug("[ComputeServerStats] Fetch error:",n),!1}}async getActiveChildren(){this.ensureNotDisposed();try{let r=await fetch(`${this.serverUrl}/activechildren`,{headers:this.buildHeaders()});if(!r.ok)return p().warn("[ComputeServerStats] Failed to fetch active children:",r.status),null;let t=await r.text(),n=parseInt(t.trim(),10);return isNaN(n)?(p().warn("[ComputeServerStats] Invalid active children response:",t),null):n}catch(r){return p().warn("[ComputeServerStats] Error fetching active children:",r),null}}async getVersion(){this.ensureNotDisposed();try{let r=await fetch(`${this.serverUrl}/version`,{headers:this.buildHeaders()});if(!r.ok)return p().warn("[ComputeServerStats] Failed to fetch version:",r.status),null;try{let t=await r.json();return{rhino:_nullishCoalesce(t.rhino, () => ("")),compute:_nullishCoalesce(t.compute, () => ("")),git_sha:_nullishCoalesce(t.git_sha, () => (null))}}catch (e4){return{rhino:await r.text(),compute:"",git_sha:null}}}catch(r){return p().warn("[ComputeServerStats] Error fetching version:",r),null}}async getServerStats(){if(this.ensureNotDisposed(),!await this.isServerOnline())return{isOnline:!1};let[t,n]=await Promise.all([this.getVersion(),this.getActiveChildren()]);return{isOnline:!0,...t&&{version:t},...n!==null&&{activeChildren:n}}}monitor(r,t=5e3){this.ensureNotDisposed();let n=!0,s=null;p().info(`\u{1F504} Starting server stats monitoring every ${t}ms`);let i=async()=>{if(s!==null&&(this.activeTimeouts.delete(s),s=null),!(!n||this.disposed)){try{let o=await this.getServerStats();if(!n||this.disposed)return;try{r(o)}catch(l){p().error("[ComputeServerStats] Monitor callback threw:",l)}}catch(o){p().error("[ComputeServerStats] Failed to fetch stats during monitor:",o)}n&&!this.disposed&&(s=setTimeout(()=>{i()},t),this.activeTimeouts.add(s))}},c=()=>{n=!1,s!==null&&(clearTimeout(s),this.activeTimeouts.delete(s),s=null),this.activeMonitors.delete(c)};return this.activeMonitors.add(c),i(),c}async dispose(){if(!this.disposed){this.disposed=!0;for(let r of this.activeMonitors)r();this.activeMonitors.clear();for(let r of this.activeTimeouts)clearTimeout(r);this.activeTimeouts.clear()}}ensureNotDisposed(){if(this.disposed)throw new d("ComputeServerStats has been disposed and cannot be used",a.INVALID_STATE,{context:{disposed:this.disposed}})}};function A(e,r={}){let{preserveSpaces:t=!1}=r,n=e.trim();return t?(n=n.charAt(0).toLowerCase()+n.slice(1).replace(/[-_](.)/g,(s,i)=>i?i.toUpperCase():""),n):(n=n.replace(/^[A-Z]/,s=>s.toLowerCase()).replace(/[\s-_]+(.)?/g,(s,i)=>i?i.toUpperCase():""),n)}function C(e,r={}){return!e||typeof e!="object"?e:Array.isArray(e)?r.deep?e.map(t=>C(t,r)):e:Object.keys(e).reduce((t,n)=>{let s=A(n,{preserveSpaces:r.preserveSpaces}),i=e[n];return t[s]=r.deep?C(i,r):i,t},{})}exports.a = W; exports.b = R; exports.c = a; exports.d = d; exports.e = p; exports.f = N; exports.g = _; exports.h = V; exports.i = E; exports.j = A; exports.k = C;
3
- //# sourceMappingURL=chunk-IJZNCO5X.cjs.map
2
+ ${u.StackTrace||""}`:_optionalChain([u, 'optionalAccess', _17 => _17.error])&&(l=typeof u.error=="string"?u.error:JSON.stringify(u.error,null,2))}catch(u){c&&f(` Failed to parse error body as JSON: ${u}`,!0)}L(e,r,t,n,s,l)}f(`\u2705 Request [${t}] completed in ${o}ms`,c);try{return await e.json()}catch(l){throw new d("Failed to parse JSON response",a.NETWORK_ERROR,{statusCode:e.status,context:{url:r,requestId:t},originalError:l instanceof Error?l:new Error(String(l))})}}async function H(e,r,t,n){let{signal:s,cleanup:i}=P(e.config.signal,e.config.timeoutMs),c=performance.now();try{let o=await fetch(e.fullUrl,{method:"POST",body:e.body,headers:e.headers,signal:s});if((I.has(o.status)||r.retryOn429&&o.status===429)&&t<n-1){let m=_nullishCoalesce(M(o.headers.get("Retry-After")), () => (w(t,r)));return await o.text().catch(()=>{}),{ok:!1,retry:!0,delayMs:m,cause:new d(`HTTP ${o.status} ${o.statusText} (will retry)`,a.NETWORK_ERROR,{statusCode:o.status,context:{requestId:e.requestId}})}}return{ok:!0,value:await F(o,e.fullUrl,e.requestId,e.requestSize,e.config.serverUrl,c,e.config.debug)}}catch(o){if(o instanceof Error&&(o.name==="AbortError"||o.name==="TimeoutError")){if(_optionalChain([e, 'access', _18 => _18.config, 'access', _19 => _19.signal, 'optionalAccess', _20 => _20.aborted])===!0)return{ok:!1,retry:!1,cause:new d("Request aborted by caller",a.UNKNOWN_ERROR,{context:{endpoint:e.endpoint,requestId:e.requestId,requestSize:e.requestSize},originalError:o})};let u=new d(`Request timed out after ${e.config.timeoutMs}ms`,a.TIMEOUT_ERROR,{context:{serverUrl:e.config.serverUrl,timeoutMs:e.config.timeoutMs,url:e.fullUrl,requestId:e.requestId,endpoint:e.endpoint,requestSize:e.requestSize}});return t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:u}:{ok:!1,retry:!1,cause:u}}if(o instanceof TypeError){let l=new d(`Network error: ${o.message}`,a.NETWORK_ERROR,{context:{serverUrl:e.config.serverUrl,url:e.fullUrl,requestId:e.requestId,endpoint:e.endpoint,requestSize:e.requestSize},originalError:o});return t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:l}:{ok:!1,retry:!1,cause:l}}if(o instanceof d){let l=o.statusCode;return l!==void 0&&(I.has(l)||r.retryOn429&&l===429)&&t<n-1?{ok:!1,retry:!0,delayMs:w(t,r),cause:o}:{ok:!1,retry:!1,cause:o}}return{ok:!1,retry:!1,cause:new d(o instanceof Error?o.message:String(o),a.UNKNOWN_ERROR,{context:{endpoint:e.endpoint,requestId:e.requestId},originalError:o instanceof Error?o:new Error(String(o))})}}finally{i()}}async function V(e,r,t){let n=K(),s=JSON.stringify(r),i=s.length,c=D(e,t.serverUrl),o=q(n,t),l=k(t.retry),u=l.attempts+1;if(t.debug){let h=(i/1024).toFixed(2),g=i>1e5?"\u26A0\uFE0F":"\u{1F680}";f(`${g} Starting compute request [${n}]: ${e} (${h}KB)`,!0)}let T={endpoint:e,body:s,requestSize:i,fullUrl:c,requestId:n,headers:o,config:t},m=null;for(let h=0;h<u;h++){let g=await H(T,l,h,u);if(g.ok)return g.value;if(!g.retry)throw g.cause;m=g.cause,t.debug&&f(`\u{1F501} Request [${n}] retrying after ${g.delayMs}ms (attempt ${h+2}/${u}): ${g.cause.message}`,!0);try{await x(g.delayMs,t.signal)}catch (e3){throw new d("Request aborted by caller",a.UNKNOWN_ERROR,{context:{endpoint:e,requestId:n,requestSize:i},originalError:m})}}throw _nullishCoalesce(m, () => (new d("Unknown error after retries",a.UNKNOWN_ERROR,{context:{endpoint:e,requestId:n,requestSize:i}})))}var E=class{constructor(r,t){R(this,"serverUrl");R(this,"apiKey");R(this,"disposed",!1);R(this,"activeMonitors",new Set);R(this,"activeTimeouts",new Set);if(!_optionalChain([r, 'optionalAccess', _21 => _21.trim, 'call', _22 => _22()]))throw new d("serverUrl is required",a.INVALID_CONFIG,{context:{serverUrl:r}});if(!r.match(/^https?:\/\//))throw new d(`Invalid serverUrl: "${r}". Must start with "http://" or "https://". For example: "http://localhost:5000" or "https://example.com"`,a.INVALID_CONFIG,{context:{serverUrl:r}});try{new URL(r)}catch(n){throw new d(`Invalid serverUrl: "${r}". Must be a valid URL. Received error: ${n instanceof Error?n.message:String(n)}`,a.INVALID_CONFIG,{context:{serverUrl:r},originalError:n instanceof Error?n:void 0})}this.apiKey=t,this.serverUrl=r.replace(/\/+$/,"")}buildHeaders(){let r={"Content-Type":"application/json"};return this.apiKey&&(r.RhinoComputeKey=this.apiKey),r}async isServerOnline(){this.ensureNotDisposed();let r=`${this.serverUrl}/healthcheck`,t={headers:this.buildHeaders(),method:"GET"};try{return(await fetch(r,t)).ok}catch(n){return p().debug("[ComputeServerStats] Fetch error:",n),!1}}async getActiveChildren(){this.ensureNotDisposed();try{let r=await fetch(`${this.serverUrl}/activechildren`,{headers:this.buildHeaders()});if(!r.ok)return p().warn("[ComputeServerStats] Failed to fetch active children:",r.status),null;let t=await r.text(),n=parseInt(t.trim(),10);return isNaN(n)?(p().warn("[ComputeServerStats] Invalid active children response:",t),null):n}catch(r){return p().warn("[ComputeServerStats] Error fetching active children:",r),null}}async getVersion(){this.ensureNotDisposed();try{let r=await fetch(`${this.serverUrl}/version`,{headers:this.buildHeaders()});if(!r.ok)return p().warn("[ComputeServerStats] Failed to fetch version:",r.status),null;let t=await r.text();try{let n=JSON.parse(t);return{rhino:_nullishCoalesce(n.rhino, () => ("")),compute:_nullishCoalesce(n.compute, () => ("")),git_sha:_nullishCoalesce(n.git_sha, () => (null))}}catch (e4){return{rhino:t,compute:"",git_sha:null}}}catch(r){return p().warn("[ComputeServerStats] Error fetching version:",r),null}}async getServerStats(){if(this.ensureNotDisposed(),!await this.isServerOnline())return{isOnline:!1};let[t,n]=await Promise.all([this.getVersion(),this.getActiveChildren()]);return{isOnline:!0,...t&&{version:t},...n!==null&&{activeChildren:n}}}monitor(r,t=5e3){this.ensureNotDisposed();let n=!0,s=null;p().info(`\u{1F504} Starting server stats monitoring every ${t}ms`);let i=async()=>{if(s!==null&&(this.activeTimeouts.delete(s),s=null),!(!n||this.disposed)){try{let o=await this.getServerStats();if(!n||this.disposed)return;try{r(o)}catch(l){p().error("[ComputeServerStats] Monitor callback threw:",l)}}catch(o){p().error("[ComputeServerStats] Failed to fetch stats during monitor:",o)}n&&!this.disposed&&(s=setTimeout(()=>{i()},t),this.activeTimeouts.add(s))}},c=()=>{n=!1,s!==null&&(clearTimeout(s),this.activeTimeouts.delete(s),s=null),this.activeMonitors.delete(c)};return this.activeMonitors.add(c),i(),c}async dispose(){if(!this.disposed){this.disposed=!0;for(let r of this.activeMonitors)r();this.activeMonitors.clear();for(let r of this.activeTimeouts)clearTimeout(r);this.activeTimeouts.clear()}}ensureNotDisposed(){if(this.disposed)throw new d("ComputeServerStats has been disposed and cannot be used",a.INVALID_STATE,{context:{disposed:this.disposed}})}};function A(e,r={}){let{preserveSpaces:t=!1}=r,n=e.trim();return t?(n=n.charAt(0).toLowerCase()+n.slice(1).replace(/[-_](.)/g,(s,i)=>i?i.toUpperCase():""),n):(n=n.replace(/^[A-Z]/,s=>s.toLowerCase()).replace(/[\s-_]+(.)?/g,(s,i)=>i?i.toUpperCase():""),n)}function C(e,r={}){return!e||typeof e!="object"?e:Array.isArray(e)?r.deep?e.map(t=>C(t,r)):e:Object.keys(e).reduce((t,n)=>{let s=A(n,{preserveSpaces:r.preserveSpaces}),i=e[n];return t[s]=r.deep?C(i,r):i,t},{})}exports.a = W; exports.b = R; exports.c = a; exports.d = d; exports.e = p; exports.f = N; exports.g = _; exports.h = V; exports.i = E; exports.j = A; exports.k = C;
3
+ //# sourceMappingURL=chunk-XULONXVP.cjs.map