selva-compute 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -56
- package/dist/{chunk-P57VU27W.cjs → chunk-FNWG34KH.cjs} +2 -2
- package/dist/chunk-FNWG34KH.cjs.map +1 -0
- package/dist/chunk-G6W5VE7C.cjs +2 -0
- package/dist/chunk-G6W5VE7C.cjs.map +1 -0
- package/dist/chunk-I3OX3G7J.js +2 -0
- package/dist/chunk-I3OX3G7J.js.map +1 -0
- package/dist/{chunk-5DJRUPGI.cjs → chunk-M2HPEWXH.cjs} +2 -2
- package/dist/chunk-M2HPEWXH.cjs.map +1 -0
- package/dist/{chunk-AEQTQHPY.js → chunk-QFHFH5BS.js} +2 -2
- package/dist/chunk-QFHFH5BS.js.map +1 -0
- package/dist/{chunk-24EXIE4G.js → chunk-VGM4KAFN.js} +2 -2
- package/dist/chunk-VGM4KAFN.js.map +1 -0
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1 -1
- package/dist/grasshopper.cjs +1 -1
- package/dist/grasshopper.cjs.map +1 -1
- package/dist/grasshopper.d.cts +93 -7
- package/dist/grasshopper.d.ts +93 -7
- package/dist/grasshopper.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1 -1
- package/dist/{schemas-5LuPKgX2.d.cts → schemas-CQEJ5EZy.d.cts} +1 -1
- package/dist/{schemas-5LuPKgX2.d.ts → schemas-CQEJ5EZy.d.ts} +1 -1
- package/dist/visualization.cjs +1 -1
- package/dist/visualization.cjs.map +1 -1
- package/dist/visualization.d.cts +1 -1
- package/dist/visualization.d.ts +1 -1
- package/dist/visualization.js +1 -1
- package/dist/visualization.js.map +1 -1
- package/package.json +17 -7
- package/dist/chunk-24EXIE4G.js.map +0 -1
- package/dist/chunk-5DJRUPGI.cjs.map +0 -1
- package/dist/chunk-AEQTQHPY.js.map +0 -1
- package/dist/chunk-JJLRDYYP.js +0 -2
- package/dist/chunk-JJLRDYYP.js.map +0 -1
- package/dist/chunk-OXD76DAK.js +0 -2
- package/dist/chunk-OXD76DAK.js.map +0 -1
- package/dist/chunk-P57VU27W.cjs.map +0 -1
- package/dist/chunk-PNG3L5TM.cjs +0 -2
- package/dist/chunk-PNG3L5TM.cjs.map +0 -1
- package/dist/chunk-TVCJBLSW.cjs +0 -2
- package/dist/chunk-TVCJBLSW.cjs.map +0 -1
- package/dist/files.cjs +0 -2
- package/dist/files.cjs.map +0 -1
- package/dist/files.d.cts +0 -34
- package/dist/files.d.ts +0 -34
- package/dist/files.js +0 -2
- package/dist/files.js.map +0 -1
- package/dist/types-SwbLAMW8.d.cts +0 -27
- package/dist/types-SwbLAMW8.d.ts +0 -27
package/README.md
CHANGED
|
@@ -12,61 +12,6 @@ npm install selva-compute three
|
|
|
12
12
|
|
|
13
13
|
_(Note: `three` is a peer dependency if you use the visualization features)_
|
|
14
14
|
|
|
15
|
-
## Quick Start
|
|
16
|
-
|
|
17
|
-
### 1. Initialize the Client
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
import { RhinoComputeApp } from 'selva-compute';
|
|
21
|
-
|
|
22
|
-
const app = new RhinoComputeApp({
|
|
23
|
-
url: 'http://localhost:6500/', // URL of your Rhino Compute instance
|
|
24
|
-
apiKey: 'your-auth-token', // Optional
|
|
25
|
-
debug: true // Enable logging
|
|
26
|
-
});
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### 2. Solve a Grasshopper Definition
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
// Define your inputs
|
|
33
|
-
const inputs = {
|
|
34
|
-
Length: 12.5,
|
|
35
|
-
Width: 5.0,
|
|
36
|
-
Count: 10
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
// Solve the definition
|
|
40
|
-
try {
|
|
41
|
-
const result = await app.solve('my_definition.gh', inputs);
|
|
42
|
-
|
|
43
|
-
// Access outputs
|
|
44
|
-
console.log('Results:', result.values);
|
|
45
|
-
console.log('Geometry:', result.geometry); // Decoded rhino3dm objects
|
|
46
|
-
} catch (error) {
|
|
47
|
-
console.error('Computation failed:', error);
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Features
|
|
52
|
-
|
|
53
|
-
- **Robust Client**: Handles connection, retries, and error parsing.
|
|
54
|
-
- **Smart Solving**: Automatically formats inputs and parses output trees.
|
|
55
|
-
- **Visualization Tools**: Convert Rhino geometry to Three.js objects easily.
|
|
56
|
-
```typescript
|
|
57
|
-
import { toThreeJs } from 'selva-compute/visualization';
|
|
58
|
-
const mesh = toThreeJs(rhinoMesh);
|
|
59
|
-
scene.add(mesh);
|
|
60
|
-
```
|
|
61
|
-
- **File Utils**: Helpers for handling base64 encoding/decoding of Rhino files.
|
|
62
|
-
|
|
63
|
-
## Exports
|
|
64
|
-
|
|
65
|
-
- `selva-compute` - Main entry point (Client, App).
|
|
66
|
-
- `selva-compute/grasshopper` - Grasshopper client and types.
|
|
67
|
-
- `selva-compute/visualization` - Three.js conversion helpers.
|
|
68
|
-
- `selva-compute/files` - File utilities.
|
|
69
|
-
|
|
70
15
|
## Requirements
|
|
71
16
|
|
|
72
17
|
### Server Side
|
|
@@ -81,7 +26,7 @@ try {
|
|
|
81
26
|
### Client Side
|
|
82
27
|
|
|
83
28
|
- Node.js >= 20
|
|
84
|
-
- Optional: `three` >= 0.
|
|
29
|
+
- Optional: `three` >= 0.179.0 for visualization features
|
|
85
30
|
|
|
86
31
|
## License
|
|
87
32
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 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 E=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 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 E=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var $=(r,e,t)=>e in r?E(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var f=(r,e)=>()=>(r&&(e=r(r=0)),e);var _=(r,e)=>{for(var t in e)E(r,t,{get:e[t],enumerable:!0})},L=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of I(e))!x.call(r,n)&&n!==t&&E(r,n,{get:()=>e[n],enumerable:!(o=S(e,n))||o.enumerable});return r};var F=r=>L(E({},"__esModule",{value:!0}),r);var d=(r,e,t)=>$(r,typeof e!="symbol"?e+"":e,t);var p,w= exports.e =f(()=>{"use strict";p= exports.d =class extends Error{constructor(t,o="UNKNOWN_ERROR",n){super(t);d(this,"code");d(this,"statusCode");d(this,"context");d(this,"originalError");this.name="RhinoComputeError",this.code=o,this.statusCode=_optionalChain([n, 'optionalAccess', _2 => _2.statusCode]),this.context=_optionalChain([n, 'optionalAccess', _3 => _3.context]),this.originalError=_optionalChain([n, 'optionalAccess', _4 => _4.originalError]),"cause"in Error.prototype&&Object.defineProperty(this,"cause",{value:_optionalChain([n, 'optionalAccess', _5 => _5.originalError]),enumerable:!0})}}});var i,N= exports.g =f(()=>{"use strict";i= exports.f ={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 A={};_(A,{ErrorCodes:()=>i,RhinoComputeError:()=>p});var C=f(()=>{"use strict";w();N()});function l(){return v}function b(r){r===null?v=new O:"debug"in r&&"info"in r&&"warn"in r&&"error"in r?v=r:v=new T}function M(){b(new T)}var O,T,v,y= exports.m =f(()=>{"use strict";O=class{debug(){}info(){}warn(){}error(){}},T=class{debug(e,...t){console.debug(e,...t)}info(e,...t){console.info(e,...t)}warn(e,...t){console.warn(e,...t)}error(e,...t){console.error(e,...t)}},v=new O});C();y();var _computerhino3d = require('compute-rhino3d'); var _computerhino3d2 = _interopRequireDefault(_computerhino3d);function D(r,e,t,o,n,R){let{status:a,statusText:u}=r,c={url:e,requestId:t,method:"POST",requestSize:o,serverUrl:n},h={401:{message:`HTTP ${a}: ${u}`,code:i.AUTH_ERROR},403:{message:`HTTP ${a}: ${u}`,code:i.AUTH_ERROR},404:{message:`Endpoint not found: ${e}`,code:i.NETWORK_ERROR},413:{message:`Request too large: ${(o/1024).toFixed(2)}KB`,code:i.VALIDATION_ERROR},429:{message:"Rate limit exceeded",code:i.NETWORK_ERROR},500:{message:`Server error: ${R||u}`,code:i.COMPUTATION_ERROR},502:{message:`Service unavailable: ${u}`,code:i.NETWORK_ERROR},503:{message:`Service unavailable: ${u}`,code:i.NETWORK_ERROR},504:{message:`Service unavailable: ${u}`,code:i.NETWORK_ERROR}}[a]||{message:`HTTP ${a}: ${u}`,code:i.UNKNOWN_ERROR};throw new p(h.message,h.code,{statusCode:a,context:c})}function K(r,e){let t=e.replace(/\/+$/,""),o=r.replace(/^\/+/,"");return`${t}/${o}`}function k(r){try{let e=new URL(r).host;return/^(localhost|127\.0\.0\.1|::1)(:\d+)?$/i.test(e)}catch (e2){return/(localhost|127\.0\.0\.1)/i.test(r)}}function P(r,e){let t={"User-Agent":`compute.rhino3d.js/${_computerhino3d2.default.version}`,"X-Request-ID":r,"Content-Type":"application/json",...e.authToken&&{Authorization:e.authToken},...e.apiKey&&{RhinoComputeKey:e.apiKey}};return!e.apiKey&&!k(e.serverUrl)&&l().warn(`\u26A0\uFE0F [Rhino Compute] Request [${r}] targets remote server (${e.serverUrl}) but no API key is configured. Requests may fail or be rate-limited.`),t}function H(){return`${Date.now()}-${Math.random().toString(36).substring(2,11)}`}function m(r,e){e&&l().debug(r)}async function V(r,e,t,o,n,R,a){let u=Math.round(performance.now()-R);if(!r.ok){let c=await r.text();if(a&&(m(`\u274C Request [${t}] failed with HTTP ${r.status} in ${u}ms`,!0),m(` URL: ${e}`,!0),m(` Status: ${r.status} ${r.statusText}`,!0),c&&m(` Response body: ${c.substring(0,500)}${c.length>500?"...":""}`,!0)),r.status===500)try{let s=JSON.parse(c);if(_optionalChain([s, 'optionalAccess', _6 => _6.values])&&(s.errors||s.warnings))return a&&(m(`\u26A0\uFE0F Request [${t}] completed with Grasshopper errors in ${u}ms`,!0),_optionalChain([s, 'access', _7 => _7.errors, 'optionalAccess', _8 => _8.length])>0&&m(` Errors: ${JSON.stringify(s.errors,null,2)}`,!0),_optionalChain([s, 'access', _9 => _9.warnings, 'optionalAccess', _10 => _10.length])>0&&m(` Warnings: ${JSON.stringify(s.warnings,null,2)}`,!0)),s;_optionalChain([s, 'optionalAccess', _11 => _11.Message])?c=`${s.ExceptionType?s.ExceptionType+": ":""}${s.Message}
|
|
2
2
|
${s.StackTrace||""}`:_optionalChain([s, 'optionalAccess', _12 => _12.error])&&(c=typeof s.error=="string"?s.error:JSON.stringify(s.error,null,2))}catch(s){a&&m(` Failed to parse error body as JSON: ${s}`,!0)}D(r,e,t,o,n,c)}m(`\u2705 Request [${t}] completed in ${u}ms`,a);try{return await r.json()}catch(c){throw new p("Failed to parse JSON response",i.NETWORK_ERROR,{statusCode:r.status,context:{url:e,requestId:t},originalError:c instanceof Error?c:new Error(String(c))})}}async function W(r,e,t){let o=H(),n=JSON.stringify(e),R=n.length,a=K(r,t.serverUrl);if(t.debug){let s=(R/1024).toFixed(2),h=R>1e5?"\u26A0\uFE0F":"\u{1F680}";m(`${h} Starting compute request [${o}]: ${r} (${s}KB)`,!0)}let u=new AbortController,c=t.timeoutMs?setTimeout(()=>u.abort(),t.timeoutMs):null;try{let s=performance.now(),h=await fetch(a,{method:"POST",body:n,headers:P(o,t),signal:u.signal});return await V(h,a,o,R,t.serverUrl,s,t.debug)}catch(s){throw s instanceof Error&&s.name==="AbortError"&&t.timeoutMs?new p(`Request timed out after ${t.timeoutMs}ms`,i.TIMEOUT_ERROR,{context:{serverUrl:t.serverUrl,timeoutMs:t.timeoutMs,url:a,requestId:o,args:e}}):s instanceof TypeError?new p(`Network error: ${s.message}`,i.NETWORK_ERROR,{context:{serverUrl:t.serverUrl,url:a,requestId:o,endpoint:r},originalError:s}):s}finally{c!==null&&clearTimeout(c)}}C();y();var g=class{constructor(e,t){d(this,"serverUrl");d(this,"apiKey");d(this,"disposed",!1);d(this,"activeMonitors",new Set);d(this,"activeTimeouts",new Set);if(!_optionalChain([e, 'optionalAccess', _13 => _13.trim, 'call', _14 => _14()]))throw new p("serverUrl is required",i.INVALID_CONFIG,{context:{serverUrl:e}});if(!e.match(/^https?:\/\//))throw new p(`Invalid serverUrl: "${e}". Must start with "http://" or "https://". For example: "http://localhost:5000" or "https://example.com"`,i.INVALID_CONFIG,{context:{serverUrl:e}});try{new URL(e)}catch(o){throw new p(`Invalid serverUrl: "${e}". Must be a valid URL. Received error: ${o instanceof Error?o.message:String(o)}`,i.INVALID_CONFIG,{context:{serverUrl:e},originalError:o instanceof Error?o:void 0})}this.apiKey=t,this.serverUrl=e.replace(/\/+$/,"")}buildHeaders(){let e={"Content-Type":"application/json"};return this.apiKey&&(e.RhinoComputeKey=this.apiKey),e}async isServerOnline(){this.ensureNotDisposed();let e=`${this.serverUrl}/healthcheck`,t={headers:this.buildHeaders(),method:"GET"};try{return(await fetch(e,t)).ok}catch(o){return l().debug("[ComputeServerStats] Fetch error:",o),!1}}async getActiveChildren(){this.ensureNotDisposed();try{let e=await fetch(`${this.serverUrl}/activechildren`,{headers:this.buildHeaders()});if(!e.ok)return l().warn("[ComputeServerStats] Failed to fetch active children:",e.status),null;let t=await e.text(),o=parseInt(t.trim(),10);return isNaN(o)?(l().warn("[ComputeServerStats] Invalid active children response:",t),null):o}catch(e){return l().warn("[ComputeServerStats] Error fetching active children:",e),null}}async getVersion(){this.ensureNotDisposed();try{let e=await fetch(`${this.serverUrl}/version`,{headers:this.buildHeaders()});if(!e.ok)return l().warn("[ComputeServerStats] Failed to fetch version:",e.status),null;try{let t=await e.json();return{rhino:_nullishCoalesce(t.rhino, () => ("")),compute:_nullishCoalesce(t.compute, () => ("")),git_sha:_nullishCoalesce(t.git_sha, () => (null))}}catch (e3){return{rhino:await e.text(),compute:"",git_sha:null}}}catch(e){return l().warn("[ComputeServerStats] Error fetching version:",e),null}}async getServerStats(){if(this.ensureNotDisposed(),!await this.isServerOnline())return{isOnline:!1};let[t,o]=await Promise.all([this.getVersion(),this.getActiveChildren()]);return{isOnline:!0,...t&&{version:t},...o!==null&&{activeChildren:o}}}monitor(e,t=5e3){this.ensureNotDisposed();let o=!0,n=null;l().info(`\u{1F504} Starting server stats monitoring every ${t}ms`);let R=async()=>{if(n!==null&&(this.activeTimeouts.delete(n),n=null),!o||this.disposed)return;let u=await this.getServerStats();!o||this.disposed||(e(u),o&&!this.disposed&&(n=setTimeout(()=>{R()},t),this.activeTimeouts.add(n)))},a=()=>{o=!1,n!==null&&(clearTimeout(n),this.activeTimeouts.delete(n),n=null),this.activeMonitors.delete(a)};return this.activeMonitors.add(a),R(),a}async dispose(){if(!this.disposed){this.disposed=!0;for(let e of this.activeMonitors)e();this.activeMonitors.clear();for(let e of this.activeTimeouts)clearTimeout(e);this.activeTimeouts.clear()}}ensureNotDisposed(){if(this.disposed)throw new p("ComputeServerStats has been disposed and cannot be used",i.INVALID_STATE,{context:{disposed:this.disposed}})}};w();N();y();exports.a = _; exports.b = F; exports.c = d; exports.d = p; exports.e = w; exports.f = i; exports.g = N; exports.h = A; exports.i = C; exports.j = l; exports.k = b; exports.l = M; exports.m = y; exports.n = W; exports.o = g;
|
|
3
|
-
//# sourceMappingURL=chunk-
|
|
3
|
+
//# sourceMappingURL=chunk-FNWG34KH.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/chunk-FNWG34KH.cjs","../src/core/errors/base.ts","../src/core/errors/error-codes.ts","../src/core/errors/index.ts","../src/core/utils/logger.ts","../src/core/compute-fetch/compute-fetch.ts","../src/core/server/compute-server-stats.ts"],"names":["RhinoComputeError","init_base","__esmMin","message","code","options","__publicField","ErrorCodes","init_error_codes","errors_exports","__export","init_errors","getLogger","internalLogger","setLogger","logger","NoOpLogger","ConsoleLogger","enableDebugLogging","init_logger","args","throwHttpError","response","fullUrl","requestId","requestSize","serverUrl","errorBody","status","statusText","context","error"],"mappings":"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","file":"/home/runner/work/selva-compute/selva-compute/dist/chunk-FNWG34KH.cjs","sourcesContent":[null,"/**\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","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","/**\n * Error handling - explicit public API\n */\n\nexport { RhinoComputeError } from './base';\nexport { ErrorCodes } from './error-codes';\nexport type { ErrorCode } from './error-codes';\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 'selva-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 'selva-compute';\n *\n * enableDebugLogging();\n * ```\n */\nexport function enableDebugLogging(): void {\n\tsetLogger(new ConsoleLogger());\n}\n","import RhinoCompute from 'compute-rhino3d';\n\nimport { RhinoComputeError, ErrorCodes } from '../errors';\nimport { getLogger } from '../utils/logger';\n\nimport type { ComputeConfig } from '../types';\nimport type {\n\tGrasshopperComputeConfig,\n\tGrasshopperComputeResponse,\n\tIoResponseSchema\n} from '@/features/grasshopper/types';\n\n/**\n * Valid endpoints for Rhino Compute\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// 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 errorMap: Record<number, { message: string; code: string }> = {\n\t\t401: { message: `HTTP ${status}: ${statusText}`, code: ErrorCodes.AUTH_ERROR },\n\t\t403: { message: `HTTP ${status}: ${statusText}`, code: ErrorCodes.AUTH_ERROR },\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'User-Agent': `compute.rhino3d.js/${RhinoCompute.version}`,\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// 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// Main Function\n// ============================================================================\n\n//TODO: VALIDATE IF THIS DOC IS ACCURATE\n\n/**\n * Generic Rhino Compute fetch function.\n * Sends a POST request to any Compute endpoint with pre-prepared arguments.\n *\n * @public Use this for advanced low-level control over compute requests. For most use cases, prefer higher-level APIs.\n *\n * @param endpoint - The Compute API endpoint (e.g., 'grasshopper', 'io', 'mesh').\n * @param args - Pre-prepared arguments for the request.\n * @param config - Compute configuration (server URL, API key, timeout, debug).\n * @returns The parsed JSON response from the server.\n *\n * @example\n * ```typescript\n * const response = await fetchRhinoCompute(\n * 'grasshopper',\n * {\n * pointer: { url: 'https://example.com/definition.gh' },\n * values: [{ ParamName: 'x', InnerTree: { '0': [{ type: 'System.Double', data: 10 }] } }]\n * },\n * { serverUrl: 'https://compute.rhino3d.com', debug: true, timeoutMs: 30000 }\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\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 controller = new AbortController();\n\tconst timeoutId = config.timeoutMs\n\t\t? setTimeout(() => controller.abort(), config.timeoutMs)\n\t\t: null;\n\n\ttry {\n\t\tconst startTime = performance.now();\n\t\tconst response = await fetch(fullUrl, {\n\t\t\tmethod: 'POST',\n\t\t\tbody,\n\t\t\theaders: buildHeaders(requestId, config),\n\t\t\tsignal: controller.signal\n\t\t});\n\n\t\treturn await handleResponse(\n\t\t\tresponse,\n\t\t\tfullUrl,\n\t\t\trequestId,\n\t\t\trequestSize,\n\t\t\tconfig.serverUrl,\n\t\t\tstartTime,\n\t\t\tconfig.debug\n\t\t);\n\t} catch (error) {\n\t\tif (error instanceof Error && error.name === 'AbortError' && config.timeoutMs) {\n\t\t\tthrow new RhinoComputeError(\n\t\t\t\t`Request timed out after ${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: config.serverUrl,\n\t\t\t\t\t\ttimeoutMs: config.timeoutMs,\n\t\t\t\t\t\turl: fullUrl,\n\t\t\t\t\t\trequestId,\n\t\t\t\t\t\targs\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\t// Handle fetch errors (network issues, connection refused, etc.)\n\t\tif (error instanceof TypeError) {\n\t\t\tthrow new RhinoComputeError(`Network error: ${error.message}`, ErrorCodes.NETWORK_ERROR, {\n\t\t\t\tcontext: {\n\t\t\t\t\tserverUrl: config.serverUrl,\n\t\t\t\t\turl: fullUrl,\n\t\t\t\t\trequestId,\n\t\t\t\t\tendpoint\n\t\t\t\t},\n\t\t\t\toriginalError: error\n\t\t\t});\n\t\t}\n\n\t\tthrow error;\n\t} finally {\n\t\tif (timeoutId !== null) clearTimeout(timeoutId);\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\tconst _stats = await this.getServerStats();\n\n\t\t\t// Check again after async operation to prevent race condition\n\t\t\tif (!active || this.disposed) return;\n\n\t\t\tcallback(_stats);\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"]}
|
|
@@ -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 _chunkM2HPEWXHcjs = require('./chunk-M2HPEWXH.cjs');var _chunkFNWG34KHcjs = require('./chunk-FNWG34KH.cjs');_chunkFNWG34KHcjs.i.call(void 0, );_chunkFNWG34KHcjs.e.call(void 0, );_chunkFNWG34KHcjs.m.call(void 0, );var T=class e{constructor(r){_chunkFNWG34KHcjs.c.call(void 0, this,"config");_chunkFNWG34KHcjs.c.call(void 0, this,"serverStats");_chunkFNWG34KHcjs.c.call(void 0, this,"disposed",!1);this.config=this.normalizeComputeConfig(r),this.serverStats=new (0, _chunkFNWG34KHcjs.o)(this.config.serverUrl,this.config.apiKey)}static async create(r){let t=new e(r);if(!await t.serverStats.isServerOnline())throw new (0, _chunkFNWG34KHcjs.d)("Rhino Compute server is not online",_chunkFNWG34KHcjs.f.NETWORK_ERROR,{context:{serverUrl:t.config.serverUrl}});return t}getConfig(){return this.ensureNotDisposed(),{...this.config}}async getIO(r){return this.ensureNotDisposed(),C(r,this.config)}async getRawIO(r){return this.ensureNotDisposed(),b(r,this.config)}async solve(r,t){this.ensureNotDisposed();try{if(typeof r=="string"&&!_optionalChain([r, 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()]))throw new (0, _chunkFNWG34KHcjs.d)("Definition URL/content is required",_chunkFNWG34KHcjs.f.INVALID_INPUT,{context:{receivedUrl:r}});if(r instanceof Uint8Array&&r.length===0)throw new (0, _chunkFNWG34KHcjs.d)("Definition content is empty",_chunkFNWG34KHcjs.f.INVALID_INPUT);if(!await this.serverStats.isServerOnline())throw new (0, _chunkFNWG34KHcjs.d)("Rhino Compute server is not online",_chunkFNWG34KHcjs.f.NETWORK_ERROR,{context:{serverUrl:this.config.serverUrl}});let n=await P(t,r,this.config);if(n&&typeof n=="object"&&"message"in n&&!("fileData"in n))throw new (0, _chunkFNWG34KHcjs.d)(n.message||"Computation failed",_chunkFNWG34KHcjs.f.COMPUTATION_ERROR,{context:{definition:typeof r=="string"&&r.length<200?r:"...content...",inputs:t}});return n}catch(n){throw this.config.debug&&_chunkFNWG34KHcjs.j.call(void 0, ).error("Compute failed:",n),n instanceof _chunkFNWG34KHcjs.d?n:new (0, _chunkFNWG34KHcjs.d)(n instanceof Error?n.message:String(n),_chunkFNWG34KHcjs.f.COMPUTATION_ERROR,{context:{definition:typeof r=="string"&&r.length<200?r:"...content...",inputs:t},originalError:n instanceof Error?n:new Error(String(n))})}}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, _chunkFNWG34KHcjs.d)("GrasshopperClient has been disposed and cannot be used",_chunkFNWG34KHcjs.f.INVALID_STATE)}normalizeComputeConfig(r){if(!_optionalChain([r, 'access', _4 => _4.serverUrl, 'optionalAccess', _5 => _5.trim, 'call', _6 => _6()]))throw new (0, _chunkFNWG34KHcjs.d)("serverUrl is required",_chunkFNWG34KHcjs.f.INVALID_CONFIG,{context:{receivedServerUrl:r.serverUrl}});try{new URL(r.serverUrl)}catch (e2){throw new (0, _chunkFNWG34KHcjs.d)("serverUrl must be a valid URL",_chunkFNWG34KHcjs.f.INVALID_CONFIG,{context:{receivedServerUrl:r.serverUrl}})}if(r.serverUrl===""||r.serverUrl==="https://compute.rhino3d.com/")throw new (0, _chunkFNWG34KHcjs.d)("serverUrl must be set to your Compute server URL. The default public endpoint is not allowed.",_chunkFNWG34KHcjs.f.INVALID_CONFIG,{context:{receivedServerUrl:r.serverUrl}});return{...r,serverUrl:r.serverUrl.replace(/\/+$/,""),apiKey:r.apiKey,authToken:r.authToken,debug:_nullishCoalesce(r.debug, () => (!1)),suppressClientSideWarning:r.suppressClientSideWarning}}};var $=async(e,r=null)=>{try{return await Y(e,r)}catch(t){throw new (0, _chunkFNWG34KHcjs.d)("Failed to extract files from compute response",_chunkFNWG34KHcjs.f.INVALID_STATE,{context:{originalError:t instanceof Error?t.message:String(t)},originalError:t instanceof Error?t:void 0})}},R= exports.c =async(e,r,t=null)=>{if(typeof document>"u"||typeof Blob>"u")throw new (0, _chunkFNWG34KHcjs.d)("File download functionality is only available in browser environments. This function requires the DOM API (document, Blob).",_chunkFNWG34KHcjs.f.BROWSER_ONLY,{context:{environment:typeof window<"u"?"browser (SSR)":"Node.js",documentAvailable:typeof document<"u",blobAvailable:typeof Blob<"u"}});try{let n=await Y(e,t);await le(n,r)}catch(n){throw n instanceof _chunkFNWG34KHcjs.d?n:new (0, _chunkFNWG34KHcjs.d)("Failed to download files from compute response",_chunkFNWG34KHcjs.f.INVALID_STATE,{context:{originalError:n instanceof Error?n.message:String(n)},originalError:n instanceof Error?n:void 0})}},Y=async(e,r)=>{let t=[];if(e.forEach(n=>{let a=`${n.fileName}${n.fileType}`;if(n.subFolder&&n.subFolder.trim()!==""&&(a=`${n.subFolder}/${a}`),n.isBase64Encoded===!0&&n.data){let o=_chunkM2HPEWXHcjs.c.call(void 0, n.data);t.push({fileName:`${n.fileName}${n.fileType}`,content:new Uint8Array(o.buffer),path:a})}else n.isBase64Encoded===!1&&n.data&&t.push({fileName:`${n.fileName}${n.fileType}`,content:n.data,path:a})}),r){let n=Array.isArray(r)?r:[r],a=await Promise.all(n.map(async o=>{try{let s=await fetch(o.filePath);if(!s.ok)return _chunkFNWG34KHcjs.j.call(void 0, ).warn(`Failed to fetch additional file from URL: ${o.filePath}`),null;let u=await(await s.blob()).arrayBuffer();return{fileName:o.fileName,content:new Uint8Array(u),path:o.fileName}}catch(s){return _chunkFNWG34KHcjs.j.call(void 0, ).error(`Error fetching additional file from URL: ${o.filePath}`,s),null}}));t.push(...a.filter(o=>o!==null))}return t};async function le(e,r){let{zipSync:t,strToU8:n}=await Promise.resolve().then(() => _interopRequireWildcard(require("fflate"))),a={};e.forEach(i=>{a[i.path]=typeof i.content=="string"?n(i.content):i.content});let o=t(a,{level:6}),s=new Blob([o],{type:"application/zip"});pe(s,`${r}.zip`)}function pe(e,r){if(typeof document>"u")throw new (0, _chunkFNWG34KHcjs.d)("saveFile requires a browser environment with DOM API access.",_chunkFNWG34KHcjs.f.BROWSER_ONLY,{context:{function:"saveFile",requiredAPI:"document"}});let t=document.createElement("a");t.href=URL.createObjectURL(e),t.download=r,t.click(),URL.revokeObjectURL(t.href)}var N=new Map;function J(e,r){N.set(e,r)}J("Rhino.Geometry.Point3d",(e,r)=>{let t=r;return!t||typeof t.X!="number"?null:new e.Point([t.X,t.Y,t.Z])});J("Rhino.Geometry.Line",(e,r)=>{let t=r;return!t||!t.From||!t.To?null:new e.Line([t.From.X,t.From.Y,t.From.Z],[t.To.X,t.To.Y,t.To.Z])});function fe(e){if(N.has(e))return N.get(e);for(let[r,t]of N)if(e.startsWith(r))return t}function ce(e){return!e||typeof e!="object"?null:_nullishCoalesce(_nullishCoalesce(e.data, () => (e.value)), () => (null))}function X(e,r,t){let n=fe(r);if(n)try{return n(t,e)}catch(a){_chunkFNWG34KHcjs.j.call(void 0, ).warn(`Failed to decode Rhino type ${r}:`,a)}try{let a=ce(e);if(a)return t.CommonObject.decode(a)}catch(a){return _chunkFNWG34KHcjs.j.call(void 0, ).warn(`Failed to decode ${r} with CommonObject:`,a),{__decodeError:!0,type:r,raw:e}}return e}var I={STRING:"System.String",INT:"System.Int32",DOUBLE:"System.Double",BOOL:"System.Boolean"},me=["WebDisplay"],de="Rhino.Geometry.",ye="FileData";function he(e){return me.some(r=>e.includes(r))}function Z(e){if(typeof e!="string")return e;let r=e.trim();if(!(r.startsWith("{")||r.startsWith("[")||r.startsWith('"')))return e;try{let n=JSON.parse(r);if(typeof n=="string")try{return JSON.parse(n)}catch (e3){return n}return n}catch (e4){return e}}function ge(e,r,t){switch(r){case I.STRING:return typeof e!="string"?e:e.replace(/^"(.*)"$/,"$1");case I.INT:return Number.parseInt(e,10);case I.DOUBLE:return Number.parseFloat(e);case I.BOOL:return String(e).toLowerCase()==="true";default:return t&&r.startsWith(de)?X(e,r,t):e}}function H(e,r,t,n){if(he(r))return null;if(typeof e!="string")return e;let a=t?Z(e):e;return ge(a,r,n)}function F(e,r){for(let t of Object.values(e))if(Array.isArray(t))for(let n of t)r(n)}function Q(e,r=!1,t={}){let{parseValues:n=!0,rhino:a,stringOnly:o=!1}=t,s={};for(let i of e.values)F(i.InnerTree,u=>{if(o&&u.type!==I.STRING)return;let p=r?u.id:i.ParamName;if(!p)return;let m=H(u.data,u.type,n,a);s[p]===void 0?s[p]=m:Array.isArray(s[p])?s[p].push(m):s[p]=[s[p],m]});return{values:s}}function ee(e){let r=[];for(let t of e.values)F(t.InnerTree,n=>{if(!n.type.includes(ye))return;let a=Z(n.data);a&&a.FileName&&a.FileType&&a.Data&&r.push(a)});return r}function U(e,r,t={}){let{parseValues:n=!0,rhino:a,stringOnly:o=!1}=t,s;if("byName"in r?s=e.values.find(u=>u.ParamName===r.byName):s=e.values.find(u=>{let p=!1;return F(u.InnerTree,m=>{m.id===r.byId&&(p=!0)}),p}),!s)return;let i=[];if(F(s.InnerTree,u=>{if("byId"in r&&u.id!==r.byId||o&&u.type!==I.STRING)return;let p=H(u.data,u.type,n,a);i.push(p)}),i.length!==0)return i.length===1?i[0]:i}var x=class{constructor(r,t=!1){this.response=r;this.debug=t}getValues(r=!1,t={}){return Q(this.response,r,t)}getValueByParamName(r,t){return U(this.response,{byName:r},t)}getValueByParamId(r,t){return U(this.response,{byId:r},t)}async extractMeshesFromResponse(r){let t={debug:this.debug,...r};try{let{getThreeMeshesFromComputeResponse:n}=await Promise.resolve().then(() => _interopRequireWildcard(require("./visualization.cjs")));return n(this.response,t)}catch(n){let{RhinoComputeError:a,ErrorCodes:o}=(_chunkFNWG34KHcjs.i.call(void 0, ),_chunkFNWG34KHcjs.b.call(void 0, _chunkFNWG34KHcjs.h));throw new a("Failed to load three.js visualization module. Ensure three.js is installed as a peer dependency.",o.INVALID_STATE,{context:{originalError:n instanceof Error?n.message:String(n)}})}}getFileData(){return ee(this.response)}getAndDownloadFiles(r,t){let n=this.getFileData();R(n,r,t)}};_chunkFNWG34KHcjs.m.call(void 0, );function A(e,r){r||typeof window<"u"&&_chunkFNWG34KHcjs.j.call(void 0, ).warn(`Warning: ${e} is running on the client side. For better performance and security, consider running this on the server side.`)}async function P(e,r,t){t.debug&&A("solveGrasshopperDefinition",t.suppressClientSideWarning);let n=k(r,e);Te(n,t);let a=await _chunkFNWG34KHcjs.n.call(void 0, "grasshopper",n,t);return"pointer"in a&&delete a.pointer,a}function k(e,r){let t={algo:null,pointer:null,values:r};return e instanceof Uint8Array?t.algo=_chunkM2HPEWXHcjs.d.call(void 0, e):e.startsWith("http")?t.pointer=e:_chunkM2HPEWXHcjs.b.call(void 0, e)?t.algo=e:t.algo=_chunkM2HPEWXHcjs.a.call(void 0, e),t}function Te(e,r){r.cachesolve!==null&&(e.cachesolve=r.cachesolve),r.modelunits!==null&&(e.modelunits=r.modelunits),r.angletolerance!==null&&(e.angletolerance=r.angletolerance),r.absolutetolerance!==null&&(e.absolutetolerance=r.absolutetolerance),r.dataversion!==null&&(e.dataversion=r.dataversion),r.filename!==null&&(e.filename=r.filename)}function be(e,r={}){let{preserveSpaces:t=!1}=r,n=e.trim();return t?(n=n.charAt(0).toLowerCase()+n.slice(1).replace(/[-_](.)/g,(a,o)=>o?o.toUpperCase():""),n):(n=n.replace(/^[A-Z]/,a=>a.toLowerCase()).replace(/[\s-_]+(.)?/g,(a,o)=>o?o.toUpperCase():""),n)}function E(e,r={}){return!e||typeof e!="object"?e:Array.isArray(e)?r.deep?e.map(t=>E(t,r)):e:Object.keys(e).reduce((t,n)=>{let a=be(n,{preserveSpaces:r.preserveSpaces}),o=e[n];return t[a]=r.deep?E(o,r):o,t},{})}_chunkFNWG34KHcjs.i.call(void 0, );_chunkFNWG34KHcjs.e.call(void 0, );_chunkFNWG34KHcjs.g.call(void 0, );var O={invalid:(e,r,t)=>new (0, _chunkFNWG34KHcjs.d)(`Input "${e}": ${r}`,_chunkFNWG34KHcjs.f.VALIDATION_ERROR,{context:{inputName:e,reason:r,..._optionalChain([t, 'optionalAccess', _7 => _7.context])},...t}),missingValues:(e,r,t)=>new (0, _chunkFNWG34KHcjs.d)(`Input "${e}" has no values defined${r?` (expected ${r})`:""}`,_chunkFNWG34KHcjs.f.INVALID_INPUT,{context:{inputName:e,expectedType:r,..._optionalChain([t, 'optionalAccess', _8 => _8.context])},...t}),invalidBoolean:(e,r,t)=>new (0, _chunkFNWG34KHcjs.d)(`Invalid boolean value: ${e}${r?` in input "${r}"`:""}`,_chunkFNWG34KHcjs.f.VALIDATION_ERROR,{context:{receivedValue:e,inputName:r,expectedValues:["true","false"],..._optionalChain([t, 'optionalAccess', _9 => _9.context])},...t}),invalidDefault:(e,r,t,n)=>new (0, _chunkFNWG34KHcjs.d)(`ValueList input "${e}" default value "${r}" is not in available values`,_chunkFNWG34KHcjs.f.VALIDATION_ERROR,{context:{inputName:e,defaultValue:r,availableValues:t,..._optionalChain([n, 'optionalAccess', _10 => _10.context])},...n}),unknownParamType:(e,r,t)=>new (0, _chunkFNWG34KHcjs.d)(`Unknown paramType: ${e}`,_chunkFNWG34KHcjs.f.VALIDATION_ERROR,{context:{receivedParamType:e,paramName:r,..._optionalChain([t, 'optionalAccess', _11 => _11.context])},...t}),invalidStructure:(e,r,t)=>new (0, _chunkFNWG34KHcjs.d)(`Invalid input structure for "${e}" (expected ${r})`,_chunkFNWG34KHcjs.f.INVALID_INPUT,{context:{inputName:e,expectedStructure:r,..._optionalChain([t, 'optionalAccess', _12 => _12.context])},...t})};function re(e){if(typeof e.default!="object"||e.default===null)return;if(!("innerTree"in e.default)){_chunkFNWG34KHcjs.j.call(void 0, ).warn("Unexpected structure in input.default:",e.default),e.default=null;return}let r=e.default.innerTree;if(Object.keys(r).length===0){e.default=void 0;return}if(e.treeAccess||e.atMost&&e.atMost>1){let n={};for(let[a,o]of Object.entries(r))n[a]=o.map(s=>{if(typeof s.data=="string"){if(s.type==="System.Double"||s.type==="System.Int32"){let i=Number(s.data);return Number.isNaN(i)?s.data:i}if(s.type==="System.Boolean")return s.data.toLowerCase()==="true";if(s.type.startsWith("Rhino.Geometry")||s.type==="System.String")try{return JSON.parse(s.data)}catch (e5){return s.data}}return s.data});e.default=n;return}let t=[];for(let n of Object.values(r))Array.isArray(n)&&n.forEach(a=>{a&&typeof a=="object"&&"data"in a&&t.push(a.data)});t.length===0?e.default=void 0:t.length===1?e.default=t[0]:e.default=t}_chunkFNWG34KHcjs.i.call(void 0, );function G(e,r){let{transform:t,setUndefinedOnEmpty:n=!0}=r;if(!(e.default===void 0||e.default===null))if(Array.isArray(e.default)){let a=e.default.map(t).filter(o=>o!==null);e.default=a.length>0?a:void 0}else{let a=t(e.default);a!==null?e.default=a:n&&(e.default=void 0)}}function Ie(){return e=>{if(typeof e=="number")return e;if(typeof e=="string"){let r=Number(e.trim());return Number.isNaN(r)?null:r}return null}}function xe(){return e=>{if(typeof e=="boolean")return e;if(typeof e=="string"){let r=e.toLowerCase();if(r==="true")return!0;if(r==="false")return!1;throw new Error(`Invalid boolean string: "${e}"`)}return null}}function De(){return e=>typeof e=="string"?e.startsWith('"')&&e.endsWith('"')||e.startsWith('"')?e.slice(1,-1):e:null}function Pe(e="unknown"){return r=>{if(typeof r=="object"&&r!==null)return r;if(typeof r=="string"&&r.trim()!=="")try{let t=JSON.parse(r);return typeof t=="object"&&t!==null?t:(_chunkFNWG34KHcjs.j.call(void 0, ).warn(`Parsed value for input ${e} is not an object`),null)}catch(t){return _chunkFNWG34KHcjs.j.call(void 0, ).warn(`Failed to parse object value "${r}" for input ${e}`,t),null}return null}}function te(e,r,t){let n=Number(e.toFixed(r));return Math.abs(e-n)<t?n:e}function Ce(e,r=1e-8){if(!Number.isFinite(e)||e===0)return .1;let t=Math.abs(e);if(t>=1){let y=String(e).split(".")[1];if(y&&y.length>0){let h=Math.min(y.length,12),g=Math.pow(10,-h),M=Number(g.toFixed(h));return Math.abs(M-g)<r?M:g}return 1}let n=String(e),a=n.toLowerCase().match(/e(-?\d+)/);if(a){let L=Number(a[1]);if(L<0||n.toLowerCase().includes("e-")){let y=Math.abs(L),h=Math.pow(10,-y),g=Number(h.toFixed(y));return Math.abs(g-h)<r?g:h}return .1}let o=12,i=t.toFixed(o).replace(/0+$/,""),u=Math.min((i.split(".")[1]||"").length,o);if(u===0)return .1;let p=Math.pow(10,-u),m=Number(p.toFixed(u));return Math.abs(m-p)<r?m:p}function ne(e,r=1e-8){let t=e.paramType==="Integer";if(G(e,{transform:Ie()}),t){Array.isArray(e.default)?e.default=e.default.map(o=>typeof o=="number"?Math.round(o):o):typeof e.default=="number"&&(e.default=Math.round(e.default)),e.stepSize=1;return}let n=Array.isArray(e.default)?e.default[0]:e.default,a;if(typeof n=="number"&&Number.isFinite(n)&&n!==0?a=n:typeof e.minimum=="number"&&Number.isFinite(e.minimum)&&e.minimum!==0?a=e.minimum:typeof e.maximum=="number"&&Number.isFinite(e.maximum)&&e.maximum!==0&&(a=e.maximum),a!==void 0?e.stepSize=Ce(a,r):e.stepSize=.1,typeof e.stepSize=="number"){let o=0,s=String(e.stepSize),i=s.toLowerCase().match(/e(-?\d+)/);if(i?o=Math.abs(Number(i[1])):o=_nullishCoalesce(_optionalChain([s, 'access', _13 => _13.split, 'call', _14 => _14("."), 'access', _15 => _15[1], 'optionalAccess', _16 => _16.length]), () => (0)),o===0&&typeof n=="number"&&n!==0&&Math.abs(n)<1){let u=Math.ceil(-Math.log10(Math.abs(n)));Number.isFinite(u)&&u>0&&(o=u)}o=Math.min(Math.max(o,0),12),Array.isArray(e.default)?e.default=e.default.map(u=>typeof u=="number"?te(u,o,r):u):typeof e.default=="number"&&(e.default=te(e.default,o,r))}}function Re(e){try{G(e,{transform:xe(),setUndefinedOnEmpty:!1})}catch(r){throw r instanceof Error?new (0, _chunkFNWG34KHcjs.d)(r.message):r}}function Oe(e){G(e,{transform:De(),setUndefinedOnEmpty:!1})}function ae(e){G(e,{transform:Pe(e.nickname||"unnamed"),setUndefinedOnEmpty:!0})}function ve(e){if(!e.values||typeof e.values!="object"||Object.keys(e.values).length===0)throw O.missingValues(e.nickname||"unnamed","ValueList");if(e.default!==void 0&&e.default!==null){let r=String(e.default).toLowerCase();Object.keys(e.values).some(n=>n.toLowerCase()===r)||_chunkFNWG34KHcjs.j.call(void 0, ).warn(`ValueList input "${e.nickname||"unnamed"}" default value "${e.default}" is not in available values`)}}var oe={Number:ne,Integer:ne,Boolean:Re,Text:Oe,ValueList:ve,Geometry:ae,File:ae};_chunkFNWG34KHcjs.m.call(void 0, );function Se(e,r){switch(e.paramType){case"Number":case"Integer":return{...r,paramType:e.paramType,minimum:e.minimum,maximum:e.maximum,atLeast:e.atLeast,atMost:e.atMost,default:e.atMost>1?[0]:0};case"Boolean":return{...r,paramType:"Boolean",default:e.atMost>1?[!1]:!1};case"Text":return{...r,paramType:"Text",default:e.atMost>1?[""]:""};case"ValueList":return{...r,paramType:"ValueList",values:_nullishCoalesce(e.values, () => ({})),default:e.atMost>1?[e.default]:e.default};case"File":return{...r,paramType:"File",default:e.atMost>1?[null]:null};default:return{...r,paramType:"Geometry",default:e.atMost>1?[null]:null}}}function v(e){let r={description:e.description,name:e.name,nickname:e.nickname,treeAccess:e.treeAccess,groupName:_nullishCoalesce(e.groupName, () => ("")),id:e.id};try{re(e);let t=oe[e.paramType];if(!t)throw O.unknownParamType(e.paramType,e.name);switch(t(e),e.paramType){case"Number":case"Integer":return{...r,paramType:e.paramType,minimum:e.minimum,maximum:e.maximum,atLeast:e.atLeast,atMost:e.atMost,stepSize:e.stepSize,default:e.default};case"Boolean":return{...r,paramType:"Boolean",default:e.default};case"Text":return{...r,paramType:"Text",default:e.default};case"ValueList":return{...r,paramType:"ValueList",values:e.values,default:e.default};case"Geometry":return{...r,paramType:e.paramType,default:e.default};case"File":return{...r,paramType:e.paramType,acceptedFormats:e.acceptedFormats,default:e.default};default:throw O.unknownParamType(e.paramType,e.name)}}catch(t){if(t instanceof _chunkFNWG34KHcjs.d)return _chunkFNWG34KHcjs.j.call(void 0, ).error(`Validation error for input ${e.name||"unknown"}:`,t.message),Se(e,r);throw new (0, _chunkFNWG34KHcjs.d)(t instanceof Error?t.message:String(t),"VALIDATION_ERROR",{context:{paramName:e.name,paramType:e.paramType},originalError:t instanceof Error?t:new Error(String(t))})}}function D(e){return e.map(r=>v(r))}async function b(e,r){let t=k(e,[]),n={};t.algo&&(n.algo=t.algo),t.pointer&&(n.pointer=t.pointer);let a=await _chunkFNWG34KHcjs.n.call(void 0, "io",n,r);if(!a||typeof a!="object")throw new (0, _chunkFNWG34KHcjs.d)("Invalid IO response structure",void 0,{context:{response:a,definition:e}});if(!a||typeof a!="object")throw new (0, _chunkFNWG34KHcjs.d)("Invalid IO response structure",void 0,{context:{response:a,definition:e}});let o=E(a,{deep:!0});return{inputs:o.inputs,outputs:o.outputs}}async function C(e,r){A("fetchParsedDefinitionIO",r.suppressClientSideWarning);let{inputs:t,outputs:n}=await b(e,r);return{inputs:D(t),outputs:n}}var S=class e{constructor(r){_chunkFNWG34KHcjs.c.call(void 0, this,"innerTree");_chunkFNWG34KHcjs.c.call(void 0, this,"paramName");this.paramName=r,this.innerTree={}}append(r,t){let n=e.formatPathString(r);this.innerTree[n]||(this.innerTree[n]=[]);let a=t.map(o=>({data:e.serializeValue(o)}));return this.innerTree[n].push(...a),this}appendSingle(r,t){return this.append(r,[t])}fromDataTreeDefault(r){this.innerTree={};for(let[t,n]of Object.entries(r)){if(!Array.isArray(n))continue;let a=e.parsePathString(t);this.append(a,n)}return this}appendFlat(r){let t=Array.isArray(r)?r:[r];return this.append([0],t)}flatten(){let r=[];for(let t of Object.values(this.innerTree))if(Array.isArray(t))for(let n of t)r.push(e.deserializeValue(n.data));return r}getPaths(){return Object.keys(this.innerTree)}getPath(r){let t=e.formatPathString(r),n=this.innerTree[t];if(n)return n.map(a=>e.deserializeValue(a.data))}toComputeFormat(){return{ParamName:this.paramName,InnerTree:this.innerTree}}getInnerTree(){return this.innerTree}getParamName(){return this.paramName}static fromInputParams(r){return r.filter(t=>e.hasValidValue(t.default)).map(t=>{let n=new e(t.nickname||"unnamed"),a=t.default;if(t.treeAccess&&e.isDataTreeStructure(a))n.fromDataTreeDefault(a),e.isNumericInput(t)&&n.applyNumericConstraints(t.minimum,t.maximum,t.nickname||"unnamed");else{let o=Array.isArray(a)?a:[a],s=e.processValues(o,t);n.appendFlat(s)}return n.toComputeFormat()})}static fromInputParam(r){return e.hasValidValue(r.default)?e.fromInputParams([r])[0]:void 0}static replaceTreeValue(r,t,n){if(r.length>0&&r[0]instanceof e){let o=r,s=o.findIndex(u=>u.getParamName()===t),i=new e(t);return typeof n=="object"&&n!==null&&!Array.isArray(n)&&e.isDataTreeStructure(n)?i.fromDataTreeDefault(n):(Array.isArray(n),i.appendFlat(n)),s!==-1?o[s]=i:o.push(i),o}else{let o=r,s=o.findIndex(p=>p.ParamName===t),i=new e(t);typeof n=="object"&&n!==null&&!Array.isArray(n)&&e.isDataTreeStructure(n)?i.fromDataTreeDefault(n):(Array.isArray(n),i.appendFlat(n));let u=i.toComputeFormat();return s!==-1?o[s]=u:o.push(u),o}}static getTreeValue(r,t){if(r.length>0&&r[0]instanceof e){let o=r.find(i=>i.getParamName()===t);if(!o)return null;let s=o.flatten();return s.length===0?null:s.length===1?s[0]:s}else{let o=r.find(p=>p.ParamName===t);if(!o)return null;let s=o.InnerTree;if(!s)return null;let i=Object.keys(s)[0];if(!i)return null;let u=s[i];if(Array.isArray(u)){if(u.length===1){let p=_optionalChain([u, 'access', _17 => _17[0], 'optionalAccess', _18 => _18.data]);return p!==void 0?e.deserializeValue(p):null}return u.map(p=>_optionalChain([p, 'optionalAccess', _19 => _19.data])!==void 0?e.deserializeValue(p.data):null).filter(p=>p!==null)}return _optionalChain([u, 'optionalAccess', _20 => _20.data])!==void 0?e.deserializeValue(u.data):u}}static parsePathString(r){let t=r.match(/^\{([\d;]+)\}$/);return t?t[1].split(";").map(Number):(_chunkFNWG34KHcjs.j.call(void 0, ).warn(`Invalid TreeBuilder path format: ${r}, using [0]`),[0])}static formatPathString(r){return`{${r.join(";")}}`}applyNumericConstraints(r,t,n){for(let a of Object.values(this.innerTree))if(Array.isArray(a))for(let o of a){let s=e.deserializeValue(o.data);if(typeof s=="number"){let i=e.clampValue(s,r,t,n);o.data=e.serializeValue(i)}}}static serializeValue(r){return typeof r=="boolean"||typeof r=="number"||typeof r=="string"?r:typeof r=="object"&&r!==null?JSON.stringify(r):String(r)}static deserializeValue(r){if(typeof r=="boolean"||typeof r=="number"||typeof r!="string")return r;if(r.startsWith("{")||r.startsWith("["))try{return JSON.parse(r)}catch (e6){return r}return isNaN(Number(r))?r==="true"?!0:r==="false"?!1:r:Number(r)}static hasValidValue(r){return r==null?!1:typeof r=="string"?!0:!(Array.isArray(r)&&r.length===0||typeof r=="object"&&!Array.isArray(r)&&Object.keys(r).length===0)}static isDataTreeStructure(r){return typeof r!="object"||r===null||Array.isArray(r)?!1:Object.entries(r).every(([t,n])=>typeof t=="string"&&/^\{[\d;]+\}$/.test(t)&&Array.isArray(n))}static isNumericInput(r){return r.paramType==="Number"||r.paramType==="Integer"}static processValues(r,t){return r.map(n=>e.isNumericInput(t)&&typeof n=="number"?e.clampValue(n,t.minimum,t.maximum,t.nickname||"unnamed"):n).filter(n=>n!=null)}static clampValue(r,t,n,a){let o=r;return t!=null&&o<t&&(_chunkFNWG34KHcjs.j.call(void 0, ).warn(`${a}: ${r} below min ${t}, clamping`),o=t),n!=null&&o>n&&(_chunkFNWG34KHcjs.j.call(void 0, ).warn(`${a}: ${r} above max ${n}, clamping`),o=n),o}};exports.a = T; exports.b = $; exports.c = R; exports.d = x; exports.e = P; exports.f = v; exports.g = D; exports.h = b; exports.i = C; exports.j = S;
|
|
2
|
+
//# sourceMappingURL=chunk-G6W5VE7C.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/chunk-G6W5VE7C.cjs","../src/features/grasshopper/client/grasshopper-client.ts","../src/features/grasshopper/file-handling/handle-files.ts"],"names":["init_errors","init_base","init_logger","GrasshopperClient","_GrasshopperClient","config","__publicField","ComputeServerStats","client","RhinoComputeError","ErrorCodes","definition","fetchParsedDefinitionIO","fetchDefinitionIO","dataTree","result","solveGrasshopperDefinition","error","getLogger","extractFilesFromComputeResponse","downloadableFiles","additionalFiles","processFiles","err","downloadFileData","fileFoldername","processedFiles","createAndDownloadZip","dataItems","item","filePath"],"mappings":"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","file":"/home/runner/work/selva-compute/selva-compute/dist/chunk-G6W5VE7C.cjs","sourcesContent":[null,"import { ErrorCodes } from '@/core/errors';\nimport { RhinoComputeError } from '@/core/errors/base';\nimport { getLogger } from '@/core/utils/logger';\nimport ComputeServerStats from '@/core/server/compute-server-stats';\nimport { ComputeConfig } from '@/core/types';\n\nimport { fetchDefinitionIO, fetchParsedDefinitionIO, solveGrasshopperDefinition } from '..';\nimport { GrasshopperComputeConfig, GrasshopperComputeResponse, DataTree } from '../types';\n\n/**\n * GrasshopperClient provides a simple API for interacting with a Rhino Compute server and grasshopper.\n *\n * @public This is the recommended high-level API for Rhino Compute operations.\n *\n * **Security Warning:**\n * Using this client in a browser environment exposes your server URL and API key to users.\n * For production, use this library server-side or proxy requests through your own backend.\n *\n * @example\n * ```typescript\n * const client = await GrasshopperClient.create({\n * serverUrl: 'http://localhost:6500',\n * apiKey: 'your-api-key'\n * });\n *\n * try {\n * const result = await client.solve(definitionUrl, { x: 1, y: 2 });\n * } finally {\n * await client.dispose(); // Clean up resources\n * }\n * ```\n */\nexport default class GrasshopperClient {\n\tprivate readonly config: GrasshopperComputeConfig;\n\tpublic readonly serverStats: ComputeServerStats;\n\tprivate disposed = false;\n\n\tprivate constructor(config: GrasshopperComputeConfig) {\n\t\tthis.config = this.normalizeComputeConfig(config);\n\t\tthis.serverStats = new ComputeServerStats(this.config.serverUrl, this.config.apiKey);\n\t}\n\n\t/**\n\t * Creates and initializes a GrasshopperClient with server validation.\n\t *\n\t * @throws {RhinoComputeError} with code NETWORK_ERROR if server is offline\n\t * @throws {RhinoComputeError} with code INVALID_CONFIG if configuration is invalid\n\t */\n\tstatic async create(config: GrasshopperComputeConfig): Promise<GrasshopperClient> {\n\t\tconst client = new GrasshopperClient(config);\n\n\t\t// Check server is online before returning\n\t\tif (!(await client.serverStats.isServerOnline())) {\n\t\t\tthrow new RhinoComputeError('Rhino Compute server is not online', ErrorCodes.NETWORK_ERROR, {\n\t\t\t\tcontext: { serverUrl: client.config.serverUrl }\n\t\t\t});\n\t\t}\n\n\t\treturn client;\n\t}\n\n\t/**\n\t * Gets the client's configuration.\n\t * Useful for passing to lower-level functions.\n\t */\n\tpublic getConfig(): GrasshopperComputeConfig {\n\t\tthis.ensureNotDisposed();\n\t\treturn { ...this.config };\n\t}\n\n\t/**\n\t * Get input/output parameters of a Grasshopper definition.\n\t */\n\tpublic async getIO(definition: string | Uint8Array) {\n\t\tthis.ensureNotDisposed();\n\t\treturn fetchParsedDefinitionIO(definition, this.config);\n\t}\n\n\tpublic async getRawIO(definition: string | Uint8Array) {\n\t\tthis.ensureNotDisposed();\n\t\treturn fetchDefinitionIO(definition, this.config);\n\t}\n\n\t/**\n\t * Run a compute job with a Grasshopper definition.\n\t *\n\t * @throws {RhinoComputeError} with code INVALID_INPUT if definition is empty\n\t * @throws {RhinoComputeError} with code NETWORK_ERROR if server is offline\n\t * @throws {RhinoComputeError} with code COMPUTATION_ERROR if computation fails\n\t */\n\tpublic async solve(\n\t\tdefinition: string | Uint8Array,\n\t\tdataTree: DataTree[]\n\t): Promise<GrasshopperComputeResponse> {\n\t\tthis.ensureNotDisposed();\n\n\t\ttry {\n\t\t\t// Validate inputs\n\t\t\tif (typeof definition === 'string' && !definition?.trim()) {\n\t\t\t\tthrow new RhinoComputeError(\n\t\t\t\t\t'Definition URL/content is required',\n\t\t\t\t\tErrorCodes.INVALID_INPUT,\n\t\t\t\t\t{\n\t\t\t\t\t\tcontext: { receivedUrl: definition }\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} else if (definition instanceof Uint8Array && definition.length === 0) {\n\t\t\t\tthrow new RhinoComputeError('Definition content is empty', ErrorCodes.INVALID_INPUT);\n\t\t\t}\n\n\t\t\t// Check server\n\t\t\tif (!(await this.serverStats.isServerOnline())) {\n\t\t\t\tthrow new RhinoComputeError(\n\t\t\t\t\t'Rhino Compute server is not online',\n\t\t\t\t\tErrorCodes.NETWORK_ERROR,\n\t\t\t\t\t{ context: { serverUrl: this.config.serverUrl } }\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Run computation\n\t\t\tconst result = await solveGrasshopperDefinition(dataTree, definition, this.config);\n\n\t\t\t// Check for errors\n\t\t\tif (result && typeof result === 'object' && 'message' in result && !('fileData' in result)) {\n\t\t\t\tthrow new RhinoComputeError(\n\t\t\t\t\t(result as { message: string }).message || 'Computation failed',\n\t\t\t\t\tErrorCodes.COMPUTATION_ERROR,\n\t\t\t\t\t{\n\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\tdefinition:\n\t\t\t\t\t\t\t\ttypeof definition === 'string' && definition.length < 200\n\t\t\t\t\t\t\t\t\t? definition\n\t\t\t\t\t\t\t\t\t: '...content...',\n\t\t\t\t\t\t\tinputs: dataTree\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tif (this.config.debug) {\n\t\t\t\tgetLogger().error('Compute failed:', error);\n\t\t\t}\n\n\t\t\tif (error instanceof RhinoComputeError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tthrow new RhinoComputeError(\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\tErrorCodes.COMPUTATION_ERROR,\n\t\t\t\t{\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\tdefinition:\n\t\t\t\t\t\t\ttypeof definition === 'string' && definition.length < 200\n\t\t\t\t\t\t\t\t? definition\n\t\t\t\t\t\t\t\t: '...content...',\n\t\t\t\t\t\tinputs: dataTree\n\t\t\t\t\t},\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}\n\n\t/**\n\t * Disposes of client resources.\n\t * Call this when you're done using the client.\n\t */\n\tpublic async dispose(): Promise<void> {\n\t\tif (this.disposed) return;\n\n\t\tthis.disposed = true;\n\n\t\t// If serverStats has a dispose method, call it\n\t\tif ('dispose' in this.serverStats && typeof this.serverStats.dispose === 'function') {\n\t\t\tawait this.serverStats.dispose();\n\t\t}\n\n\t\t// Clear any cached data or connections if needed\n\t}\n\n\t/**\n\t * Ensures the client 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'GrasshopperClient has been disposed and cannot be used',\n\t\t\t\tErrorCodes.INVALID_STATE\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Validates and normalizes a compute configuration.\n\t *\n\t * @throws {RhinoComputeError} with code INVALID_CONFIG if configuration is invalid\n\t */\n\tprivate normalizeComputeConfig<T extends ComputeConfig | GrasshopperComputeConfig>(config: T): T {\n\t\tif (!config.serverUrl?.trim()) {\n\t\t\tthrow new RhinoComputeError('serverUrl is required', ErrorCodes.INVALID_CONFIG, {\n\t\t\t\tcontext: { receivedServerUrl: config.serverUrl }\n\t\t\t});\n\t\t}\n\n\t\t// Validate URL format\n\t\ttry {\n\t\t\tnew URL(config.serverUrl);\n\t\t} catch {\n\t\t\tthrow new RhinoComputeError('serverUrl must be a valid URL', ErrorCodes.INVALID_CONFIG, {\n\t\t\t\tcontext: { receivedServerUrl: config.serverUrl }\n\t\t\t});\n\t\t}\n\n\t\t// Validate that it's not the default public endpoint\n\t\tif (config.serverUrl === '' || config.serverUrl === 'https://compute.rhino3d.com/') {\n\t\t\tthrow new RhinoComputeError(\n\t\t\t\t'serverUrl must be set to your Compute server URL. The default public endpoint is not allowed.',\n\t\t\t\tErrorCodes.INVALID_CONFIG,\n\t\t\t\t{ context: { receivedServerUrl: config.serverUrl } }\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\t...config,\n\t\t\tserverUrl: config.serverUrl.replace(/\\/+$/, ''), // Remove trailing slashes\n\t\t\tapiKey: config.apiKey,\n\t\t\tauthToken: config.authToken,\n\t\t\tdebug: config.debug ?? false,\n\t\t\tsuppressClientSideWarning: config.suppressClientSideWarning\n\t\t} as T;\n\t}\n}\n","import { RhinoComputeError, ErrorCodes, getLogger } from '@/core';\nimport { decodeBase64ToBinary } from '@/core/utils/encoding';\n\nimport { FileBaseInfo, FileData, ProcessedFile } from './types';\n\n/**\n * Extracts and processes files from compute response data without downloading them.\n * Returns an array of ProcessedFile objects that can be used programmatically.\n *\n * @param downloadableFiles - An array of FileData items from the compute response.\n * @param additionalFiles - Optional additional files to include (fetched from URLs).\n * @returns A Promise resolving to an array of ProcessedFile objects.\n * @throws Will throw an error if file processing fails.\n *\n * @example\n * const files = await extractFilesFromComputeResponse(fileData);\n * files.forEach(file => {\n * console.log(`File: ${file.fileName}, Size: ${file.content.length}`);\n * });\n */\nexport const extractFilesFromComputeResponse = async (\n\tdownloadableFiles: FileData[],\n\tadditionalFiles: FileBaseInfo[] | FileBaseInfo | null = null\n): Promise<ProcessedFile[]> => {\n\ttry {\n\t\treturn await processFiles(downloadableFiles, additionalFiles);\n\t} catch (err) {\n\t\tthrow new RhinoComputeError(\n\t\t\t'Failed to extract files from compute response',\n\t\t\tErrorCodes.INVALID_STATE,\n\t\t\t{\n\t\t\t\tcontext: { originalError: err instanceof Error ? err.message : String(err) },\n\t\t\t\toriginalError: err instanceof Error ? err : undefined\n\t\t\t}\n\t\t);\n\t}\n};\n\n/**\n * Downloads files from a compute response as a ZIP archive.\n * Packages multiple files into a single ZIP file and triggers a browser download.\n *\n * @param downloadableFiles - An array of FileData items from the compute response.\n * @param additionalFiles - Optional additional files to include in the ZIP (fetched from URLs).\n * @param fileFoldername - The name of the ZIP file (without extension).\n * @throws Will throw an error if the file handling or download fails.\n *\n * @example\n * await downloadDataFromComputeResponse(fileData, null, 'my-export');\n * // Downloads 'my-export.zip'\n */\nexport const downloadFileData = async (\n\tdownloadableFiles: FileData[],\n\tfileFoldername: string,\n\tadditionalFiles: FileBaseInfo[] | FileBaseInfo | null = null\n): Promise<void> => {\n\t// Check if we're in a browser environment\n\tif (typeof document === 'undefined' || typeof Blob === 'undefined') {\n\t\tthrow new RhinoComputeError(\n\t\t\t'File download functionality is only available in browser environments. This function requires the DOM API (document, Blob).',\n\t\t\tErrorCodes.BROWSER_ONLY,\n\t\t\t{\n\t\t\t\tcontext: {\n\t\t\t\t\tenvironment: typeof window !== 'undefined' ? 'browser (SSR)' : 'Node.js',\n\t\t\t\t\tdocumentAvailable: typeof document !== 'undefined',\n\t\t\t\t\tblobAvailable: typeof Blob !== 'undefined'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\ttry {\n\t\tconst processedFiles = await processFiles(downloadableFiles, additionalFiles);\n\t\tawait createAndDownloadZip(processedFiles, fileFoldername);\n\t} catch (err) {\n\t\t// Re-throw if it's already a RhinoComputeError\n\t\tif (err instanceof RhinoComputeError) {\n\t\t\tthrow err;\n\t\t}\n\t\tthrow new RhinoComputeError(\n\t\t\t'Failed to download files from compute response',\n\t\t\tErrorCodes.INVALID_STATE,\n\t\t\t{\n\t\t\t\tcontext: { originalError: err instanceof Error ? err.message : String(err) },\n\t\t\t\toriginalError: err instanceof Error ? err : undefined\n\t\t\t}\n\t\t);\n\t}\n};\n\n/**\n * Processes files from compute response data and additional files.\n * Converts base64-encoded data to binary and fetches additional files from URLs.\n *\n * @param dataItems - An array of FileData items to process.\n * @param additionalFiles - Optional additional files to fetch and include.\n * @returns A Promise resolving to an array of ProcessedFile objects.\n */\nconst processFiles = async (\n\tdataItems: FileData[],\n\tadditionalFiles: FileBaseInfo[] | FileBaseInfo | null\n): Promise<ProcessedFile[]> => {\n\tconst processedFiles: ProcessedFile[] = [];\n\n\t// Process compute response files\n\tdataItems.forEach((item) => {\n\t\tlet filePath = `${item.fileName}${item.fileType}`;\n\n\t\tif (item.subFolder && item.subFolder.trim() !== '') {\n\t\t\tfilePath = `${item.subFolder}/${filePath}`;\n\t\t}\n\n\t\tif (item.isBase64Encoded === true && item.data) {\n\t\t\tconst bites = decodeBase64ToBinary(item.data);\n\t\t\tprocessedFiles.push({\n\t\t\t\tfileName: `${item.fileName}${item.fileType}`,\n\t\t\t\tcontent: new Uint8Array(bites.buffer),\n\t\t\t\tpath: filePath\n\t\t\t});\n\t\t} else if (item.isBase64Encoded === false && item.data) {\n\t\t\tprocessedFiles.push({\n\t\t\t\tfileName: `${item.fileName}${item.fileType}`,\n\t\t\t\tcontent: item.data,\n\t\t\t\tpath: filePath\n\t\t\t});\n\t\t}\n\t});\n\n\tif (additionalFiles) {\n\t\tconst filesArray = Array.isArray(additionalFiles) ? additionalFiles : [additionalFiles];\n\t\tconst additionalProcessed = await Promise.all(\n\t\t\tfilesArray.map(async (file) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetch(file.filePath);\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tgetLogger().warn(`Failed to fetch additional file from URL: ${file.filePath}`);\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tconst fileBlob = await response.blob();\n\t\t\t\t\tconst arrayBuffer = await fileBlob.arrayBuffer();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tfileName: file.fileName,\n\t\t\t\t\t\tcontent: new Uint8Array(arrayBuffer),\n\t\t\t\t\t\tpath: file.fileName\n\t\t\t\t\t} as ProcessedFile;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tgetLogger().error(`Error fetching additional file from URL: ${file.filePath}`, error);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tprocessedFiles.push(...additionalProcessed.filter((f): f is ProcessedFile => f !== null));\n\t}\n\n\treturn processedFiles;\n};\n\n/**\n * Creates a ZIP archive from processed files and triggers a browser download.\n *\n * @param files - An array of ProcessedFile objects to include in the ZIP.\n * @param zipName - The name of the ZIP file (without extension).\n * @returns A Promise that resolves when the ZIP is generated and download is triggered.\n */\nasync function createAndDownloadZip(files: ProcessedFile[], zipName: string): Promise<void> {\n\tconst { zipSync, strToU8 } = await import('fflate');\n\n\t// Convert files to fflate format\n\tconst zipData: Record<string, Uint8Array> = {};\n\tfiles.forEach((file) => {\n\t\tzipData[file.path] = typeof file.content === 'string' ? strToU8(file.content) : file.content;\n\t});\n\n\tconst zipped = zipSync(zipData, { level: 6 });\n\n\tconst blob = new Blob([zipped as BlobPart], { type: 'application/zip' });\n\tsaveFile(blob, `${zipName}.zip`);\n}\n\n/**\n * Saves a Blob object as a file in the user's browser.\n *\n * @param blob - The Blob object representing the file content.\n * @param filename - The name to give the downloaded file (including extension).\n * @throws {RhinoComputeError} If not running in a browser environment.\n */\nfunction saveFile(blob: Blob, filename: string) {\n\tif (typeof document === 'undefined') {\n\t\tthrow new RhinoComputeError(\n\t\t\t'saveFile requires a browser environment with DOM API access.',\n\t\t\tErrorCodes.BROWSER_ONLY,\n\t\t\t{\n\t\t\t\tcontext: { function: 'saveFile', requiredAPI: 'document' }\n\t\t\t}\n\t\t);\n\t}\n\n\tconst a = document.createElement('a');\n\ta.href = URL.createObjectURL(blob);\n\ta.download = filename;\n\ta.click();\n\tURL.revokeObjectURL(a.href);\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as W,b as _,c as q,d as K}from"./chunk-QFHFH5BS.js";import{b as se,c as d,d as l,e as j,f,g as ie,h as ue,i as V,j as c,m as B,n as w,o as z}from"./chunk-VGM4KAFN.js";V();j();B();var T=class e{constructor(r){d(this,"config");d(this,"serverStats");d(this,"disposed",!1);this.config=this.normalizeComputeConfig(r),this.serverStats=new z(this.config.serverUrl,this.config.apiKey)}static async create(r){let t=new e(r);if(!await t.serverStats.isServerOnline())throw new l("Rhino Compute server is not online",f.NETWORK_ERROR,{context:{serverUrl:t.config.serverUrl}});return t}getConfig(){return this.ensureNotDisposed(),{...this.config}}async getIO(r){return this.ensureNotDisposed(),C(r,this.config)}async getRawIO(r){return this.ensureNotDisposed(),b(r,this.config)}async solve(r,t){this.ensureNotDisposed();try{if(typeof r=="string"&&!r?.trim())throw new l("Definition URL/content is required",f.INVALID_INPUT,{context:{receivedUrl:r}});if(r instanceof Uint8Array&&r.length===0)throw new l("Definition content is empty",f.INVALID_INPUT);if(!await this.serverStats.isServerOnline())throw new l("Rhino Compute server is not online",f.NETWORK_ERROR,{context:{serverUrl:this.config.serverUrl}});let n=await P(t,r,this.config);if(n&&typeof n=="object"&&"message"in n&&!("fileData"in n))throw new l(n.message||"Computation failed",f.COMPUTATION_ERROR,{context:{definition:typeof r=="string"&&r.length<200?r:"...content...",inputs:t}});return n}catch(n){throw this.config.debug&&c().error("Compute failed:",n),n instanceof l?n:new l(n instanceof Error?n.message:String(n),f.COMPUTATION_ERROR,{context:{definition:typeof r=="string"&&r.length<200?r:"...content...",inputs:t},originalError:n instanceof Error?n:new Error(String(n))})}}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 l("GrasshopperClient has been disposed and cannot be used",f.INVALID_STATE)}normalizeComputeConfig(r){if(!r.serverUrl?.trim())throw new l("serverUrl is required",f.INVALID_CONFIG,{context:{receivedServerUrl:r.serverUrl}});try{new URL(r.serverUrl)}catch{throw new l("serverUrl must be a valid URL",f.INVALID_CONFIG,{context:{receivedServerUrl:r.serverUrl}})}if(r.serverUrl===""||r.serverUrl==="https://compute.rhino3d.com/")throw new l("serverUrl must be set to your Compute server URL. The default public endpoint is not allowed.",f.INVALID_CONFIG,{context:{receivedServerUrl:r.serverUrl}});return{...r,serverUrl:r.serverUrl.replace(/\/+$/,""),apiKey:r.apiKey,authToken:r.authToken,debug:r.debug??!1,suppressClientSideWarning:r.suppressClientSideWarning}}};var $=async(e,r=null)=>{try{return await Y(e,r)}catch(t){throw new l("Failed to extract files from compute response",f.INVALID_STATE,{context:{originalError:t instanceof Error?t.message:String(t)},originalError:t instanceof Error?t:void 0})}},R=async(e,r,t=null)=>{if(typeof document>"u"||typeof Blob>"u")throw new l("File download functionality is only available in browser environments. This function requires the DOM API (document, Blob).",f.BROWSER_ONLY,{context:{environment:typeof window<"u"?"browser (SSR)":"Node.js",documentAvailable:typeof document<"u",blobAvailable:typeof Blob<"u"}});try{let n=await Y(e,t);await le(n,r)}catch(n){throw n instanceof l?n:new l("Failed to download files from compute response",f.INVALID_STATE,{context:{originalError:n instanceof Error?n.message:String(n)},originalError:n instanceof Error?n:void 0})}},Y=async(e,r)=>{let t=[];if(e.forEach(n=>{let a=`${n.fileName}${n.fileType}`;if(n.subFolder&&n.subFolder.trim()!==""&&(a=`${n.subFolder}/${a}`),n.isBase64Encoded===!0&&n.data){let o=q(n.data);t.push({fileName:`${n.fileName}${n.fileType}`,content:new Uint8Array(o.buffer),path:a})}else n.isBase64Encoded===!1&&n.data&&t.push({fileName:`${n.fileName}${n.fileType}`,content:n.data,path:a})}),r){let n=Array.isArray(r)?r:[r],a=await Promise.all(n.map(async o=>{try{let s=await fetch(o.filePath);if(!s.ok)return c().warn(`Failed to fetch additional file from URL: ${o.filePath}`),null;let u=await(await s.blob()).arrayBuffer();return{fileName:o.fileName,content:new Uint8Array(u),path:o.fileName}}catch(s){return c().error(`Error fetching additional file from URL: ${o.filePath}`,s),null}}));t.push(...a.filter(o=>o!==null))}return t};async function le(e,r){let{zipSync:t,strToU8:n}=await import("fflate"),a={};e.forEach(i=>{a[i.path]=typeof i.content=="string"?n(i.content):i.content});let o=t(a,{level:6}),s=new Blob([o],{type:"application/zip"});pe(s,`${r}.zip`)}function pe(e,r){if(typeof document>"u")throw new l("saveFile requires a browser environment with DOM API access.",f.BROWSER_ONLY,{context:{function:"saveFile",requiredAPI:"document"}});let t=document.createElement("a");t.href=URL.createObjectURL(e),t.download=r,t.click(),URL.revokeObjectURL(t.href)}var N=new Map;function J(e,r){N.set(e,r)}J("Rhino.Geometry.Point3d",(e,r)=>{let t=r;return!t||typeof t.X!="number"?null:new e.Point([t.X,t.Y,t.Z])});J("Rhino.Geometry.Line",(e,r)=>{let t=r;return!t||!t.From||!t.To?null:new e.Line([t.From.X,t.From.Y,t.From.Z],[t.To.X,t.To.Y,t.To.Z])});function fe(e){if(N.has(e))return N.get(e);for(let[r,t]of N)if(e.startsWith(r))return t}function ce(e){return!e||typeof e!="object"?null:e.data??e.value??null}function X(e,r,t){let n=fe(r);if(n)try{return n(t,e)}catch(a){c().warn(`Failed to decode Rhino type ${r}:`,a)}try{let a=ce(e);if(a)return t.CommonObject.decode(a)}catch(a){return c().warn(`Failed to decode ${r} with CommonObject:`,a),{__decodeError:!0,type:r,raw:e}}return e}var I={STRING:"System.String",INT:"System.Int32",DOUBLE:"System.Double",BOOL:"System.Boolean"},me=["WebDisplay"],de="Rhino.Geometry.",ye="FileData";function he(e){return me.some(r=>e.includes(r))}function Z(e){if(typeof e!="string")return e;let r=e.trim();if(!(r.startsWith("{")||r.startsWith("[")||r.startsWith('"')))return e;try{let n=JSON.parse(r);if(typeof n=="string")try{return JSON.parse(n)}catch{return n}return n}catch{return e}}function ge(e,r,t){switch(r){case I.STRING:return typeof e!="string"?e:e.replace(/^"(.*)"$/,"$1");case I.INT:return Number.parseInt(e,10);case I.DOUBLE:return Number.parseFloat(e);case I.BOOL:return String(e).toLowerCase()==="true";default:return t&&r.startsWith(de)?X(e,r,t):e}}function H(e,r,t,n){if(he(r))return null;if(typeof e!="string")return e;let a=t?Z(e):e;return ge(a,r,n)}function F(e,r){for(let t of Object.values(e))if(Array.isArray(t))for(let n of t)r(n)}function Q(e,r=!1,t={}){let{parseValues:n=!0,rhino:a,stringOnly:o=!1}=t,s={};for(let i of e.values)F(i.InnerTree,u=>{if(o&&u.type!==I.STRING)return;let p=r?u.id:i.ParamName;if(!p)return;let m=H(u.data,u.type,n,a);s[p]===void 0?s[p]=m:Array.isArray(s[p])?s[p].push(m):s[p]=[s[p],m]});return{values:s}}function ee(e){let r=[];for(let t of e.values)F(t.InnerTree,n=>{if(!n.type.includes(ye))return;let a=Z(n.data);a&&a.FileName&&a.FileType&&a.Data&&r.push(a)});return r}function U(e,r,t={}){let{parseValues:n=!0,rhino:a,stringOnly:o=!1}=t,s;if("byName"in r?s=e.values.find(u=>u.ParamName===r.byName):s=e.values.find(u=>{let p=!1;return F(u.InnerTree,m=>{m.id===r.byId&&(p=!0)}),p}),!s)return;let i=[];if(F(s.InnerTree,u=>{if("byId"in r&&u.id!==r.byId||o&&u.type!==I.STRING)return;let p=H(u.data,u.type,n,a);i.push(p)}),i.length!==0)return i.length===1?i[0]:i}var x=class{constructor(r,t=!1){this.response=r;this.debug=t}getValues(r=!1,t={}){return Q(this.response,r,t)}getValueByParamName(r,t){return U(this.response,{byName:r},t)}getValueByParamId(r,t){return U(this.response,{byId:r},t)}async extractMeshesFromResponse(r){let t={debug:this.debug,...r};try{let{getThreeMeshesFromComputeResponse:n}=await import("./visualization.js");return n(this.response,t)}catch(n){let{RhinoComputeError:a,ErrorCodes:o}=(V(),se(ue));throw new a("Failed to load three.js visualization module. Ensure three.js is installed as a peer dependency.",o.INVALID_STATE,{context:{originalError:n instanceof Error?n.message:String(n)}})}}getFileData(){return ee(this.response)}getAndDownloadFiles(r,t){let n=this.getFileData();R(n,r,t)}};B();function A(e,r){r||typeof window<"u"&&c().warn(`Warning: ${e} is running on the client side. For better performance and security, consider running this on the server side.`)}async function P(e,r,t){t.debug&&A("solveGrasshopperDefinition",t.suppressClientSideWarning);let n=k(r,e);Te(n,t);let a=await w("grasshopper",n,t);return"pointer"in a&&delete a.pointer,a}function k(e,r){let t={algo:null,pointer:null,values:r};return e instanceof Uint8Array?t.algo=K(e):e.startsWith("http")?t.pointer=e:_(e)?t.algo=e:t.algo=W(e),t}function Te(e,r){r.cachesolve!==null&&(e.cachesolve=r.cachesolve),r.modelunits!==null&&(e.modelunits=r.modelunits),r.angletolerance!==null&&(e.angletolerance=r.angletolerance),r.absolutetolerance!==null&&(e.absolutetolerance=r.absolutetolerance),r.dataversion!==null&&(e.dataversion=r.dataversion),r.filename!==null&&(e.filename=r.filename)}function be(e,r={}){let{preserveSpaces:t=!1}=r,n=e.trim();return t?(n=n.charAt(0).toLowerCase()+n.slice(1).replace(/[-_](.)/g,(a,o)=>o?o.toUpperCase():""),n):(n=n.replace(/^[A-Z]/,a=>a.toLowerCase()).replace(/[\s-_]+(.)?/g,(a,o)=>o?o.toUpperCase():""),n)}function E(e,r={}){return!e||typeof e!="object"?e:Array.isArray(e)?r.deep?e.map(t=>E(t,r)):e:Object.keys(e).reduce((t,n)=>{let a=be(n,{preserveSpaces:r.preserveSpaces}),o=e[n];return t[a]=r.deep?E(o,r):o,t},{})}V();j();ie();var O={invalid:(e,r,t)=>new l(`Input "${e}": ${r}`,f.VALIDATION_ERROR,{context:{inputName:e,reason:r,...t?.context},...t}),missingValues:(e,r,t)=>new l(`Input "${e}" has no values defined${r?` (expected ${r})`:""}`,f.INVALID_INPUT,{context:{inputName:e,expectedType:r,...t?.context},...t}),invalidBoolean:(e,r,t)=>new l(`Invalid boolean value: ${e}${r?` in input "${r}"`:""}`,f.VALIDATION_ERROR,{context:{receivedValue:e,inputName:r,expectedValues:["true","false"],...t?.context},...t}),invalidDefault:(e,r,t,n)=>new l(`ValueList input "${e}" default value "${r}" is not in available values`,f.VALIDATION_ERROR,{context:{inputName:e,defaultValue:r,availableValues:t,...n?.context},...n}),unknownParamType:(e,r,t)=>new l(`Unknown paramType: ${e}`,f.VALIDATION_ERROR,{context:{receivedParamType:e,paramName:r,...t?.context},...t}),invalidStructure:(e,r,t)=>new l(`Invalid input structure for "${e}" (expected ${r})`,f.INVALID_INPUT,{context:{inputName:e,expectedStructure:r,...t?.context},...t})};function re(e){if(typeof e.default!="object"||e.default===null)return;if(!("innerTree"in e.default)){c().warn("Unexpected structure in input.default:",e.default),e.default=null;return}let r=e.default.innerTree;if(Object.keys(r).length===0){e.default=void 0;return}if(e.treeAccess||e.atMost&&e.atMost>1){let n={};for(let[a,o]of Object.entries(r))n[a]=o.map(s=>{if(typeof s.data=="string"){if(s.type==="System.Double"||s.type==="System.Int32"){let i=Number(s.data);return Number.isNaN(i)?s.data:i}if(s.type==="System.Boolean")return s.data.toLowerCase()==="true";if(s.type.startsWith("Rhino.Geometry")||s.type==="System.String")try{return JSON.parse(s.data)}catch{return s.data}}return s.data});e.default=n;return}let t=[];for(let n of Object.values(r))Array.isArray(n)&&n.forEach(a=>{a&&typeof a=="object"&&"data"in a&&t.push(a.data)});t.length===0?e.default=void 0:t.length===1?e.default=t[0]:e.default=t}V();function G(e,r){let{transform:t,setUndefinedOnEmpty:n=!0}=r;if(!(e.default===void 0||e.default===null))if(Array.isArray(e.default)){let a=e.default.map(t).filter(o=>o!==null);e.default=a.length>0?a:void 0}else{let a=t(e.default);a!==null?e.default=a:n&&(e.default=void 0)}}function Ie(){return e=>{if(typeof e=="number")return e;if(typeof e=="string"){let r=Number(e.trim());return Number.isNaN(r)?null:r}return null}}function xe(){return e=>{if(typeof e=="boolean")return e;if(typeof e=="string"){let r=e.toLowerCase();if(r==="true")return!0;if(r==="false")return!1;throw new Error(`Invalid boolean string: "${e}"`)}return null}}function De(){return e=>typeof e=="string"?e.startsWith('"')&&e.endsWith('"')||e.startsWith('"')?e.slice(1,-1):e:null}function Pe(e="unknown"){return r=>{if(typeof r=="object"&&r!==null)return r;if(typeof r=="string"&&r.trim()!=="")try{let t=JSON.parse(r);return typeof t=="object"&&t!==null?t:(c().warn(`Parsed value for input ${e} is not an object`),null)}catch(t){return c().warn(`Failed to parse object value "${r}" for input ${e}`,t),null}return null}}function te(e,r,t){let n=Number(e.toFixed(r));return Math.abs(e-n)<t?n:e}function Ce(e,r=1e-8){if(!Number.isFinite(e)||e===0)return .1;let t=Math.abs(e);if(t>=1){let y=String(e).split(".")[1];if(y&&y.length>0){let h=Math.min(y.length,12),g=Math.pow(10,-h),M=Number(g.toFixed(h));return Math.abs(M-g)<r?M:g}return 1}let n=String(e),a=n.toLowerCase().match(/e(-?\d+)/);if(a){let L=Number(a[1]);if(L<0||n.toLowerCase().includes("e-")){let y=Math.abs(L),h=Math.pow(10,-y),g=Number(h.toFixed(y));return Math.abs(g-h)<r?g:h}return .1}let o=12,i=t.toFixed(o).replace(/0+$/,""),u=Math.min((i.split(".")[1]||"").length,o);if(u===0)return .1;let p=Math.pow(10,-u),m=Number(p.toFixed(u));return Math.abs(m-p)<r?m:p}function ne(e,r=1e-8){let t=e.paramType==="Integer";if(G(e,{transform:Ie()}),t){Array.isArray(e.default)?e.default=e.default.map(o=>typeof o=="number"?Math.round(o):o):typeof e.default=="number"&&(e.default=Math.round(e.default)),e.stepSize=1;return}let n=Array.isArray(e.default)?e.default[0]:e.default,a;if(typeof n=="number"&&Number.isFinite(n)&&n!==0?a=n:typeof e.minimum=="number"&&Number.isFinite(e.minimum)&&e.minimum!==0?a=e.minimum:typeof e.maximum=="number"&&Number.isFinite(e.maximum)&&e.maximum!==0&&(a=e.maximum),a!==void 0?e.stepSize=Ce(a,r):e.stepSize=.1,typeof e.stepSize=="number"){let o=0,s=String(e.stepSize),i=s.toLowerCase().match(/e(-?\d+)/);if(i?o=Math.abs(Number(i[1])):o=s.split(".")[1]?.length??0,o===0&&typeof n=="number"&&n!==0&&Math.abs(n)<1){let u=Math.ceil(-Math.log10(Math.abs(n)));Number.isFinite(u)&&u>0&&(o=u)}o=Math.min(Math.max(o,0),12),Array.isArray(e.default)?e.default=e.default.map(u=>typeof u=="number"?te(u,o,r):u):typeof e.default=="number"&&(e.default=te(e.default,o,r))}}function Re(e){try{G(e,{transform:xe(),setUndefinedOnEmpty:!1})}catch(r){throw r instanceof Error?new l(r.message):r}}function Oe(e){G(e,{transform:De(),setUndefinedOnEmpty:!1})}function ae(e){G(e,{transform:Pe(e.nickname||"unnamed"),setUndefinedOnEmpty:!0})}function ve(e){if(!e.values||typeof e.values!="object"||Object.keys(e.values).length===0)throw O.missingValues(e.nickname||"unnamed","ValueList");if(e.default!==void 0&&e.default!==null){let r=String(e.default).toLowerCase();Object.keys(e.values).some(n=>n.toLowerCase()===r)||c().warn(`ValueList input "${e.nickname||"unnamed"}" default value "${e.default}" is not in available values`)}}var oe={Number:ne,Integer:ne,Boolean:Re,Text:Oe,ValueList:ve,Geometry:ae,File:ae};B();function Se(e,r){switch(e.paramType){case"Number":case"Integer":return{...r,paramType:e.paramType,minimum:e.minimum,maximum:e.maximum,atLeast:e.atLeast,atMost:e.atMost,default:e.atMost>1?[0]:0};case"Boolean":return{...r,paramType:"Boolean",default:e.atMost>1?[!1]:!1};case"Text":return{...r,paramType:"Text",default:e.atMost>1?[""]:""};case"ValueList":return{...r,paramType:"ValueList",values:e.values??{},default:e.atMost>1?[e.default]:e.default};case"File":return{...r,paramType:"File",default:e.atMost>1?[null]:null};default:return{...r,paramType:"Geometry",default:e.atMost>1?[null]:null}}}function v(e){let r={description:e.description,name:e.name,nickname:e.nickname,treeAccess:e.treeAccess,groupName:e.groupName??"",id:e.id};try{re(e);let t=oe[e.paramType];if(!t)throw O.unknownParamType(e.paramType,e.name);switch(t(e),e.paramType){case"Number":case"Integer":return{...r,paramType:e.paramType,minimum:e.minimum,maximum:e.maximum,atLeast:e.atLeast,atMost:e.atMost,stepSize:e.stepSize,default:e.default};case"Boolean":return{...r,paramType:"Boolean",default:e.default};case"Text":return{...r,paramType:"Text",default:e.default};case"ValueList":return{...r,paramType:"ValueList",values:e.values,default:e.default};case"Geometry":return{...r,paramType:e.paramType,default:e.default};case"File":return{...r,paramType:e.paramType,acceptedFormats:e.acceptedFormats,default:e.default};default:throw O.unknownParamType(e.paramType,e.name)}}catch(t){if(t instanceof l)return c().error(`Validation error for input ${e.name||"unknown"}:`,t.message),Se(e,r);throw new l(t instanceof Error?t.message:String(t),"VALIDATION_ERROR",{context:{paramName:e.name,paramType:e.paramType},originalError:t instanceof Error?t:new Error(String(t))})}}function D(e){return e.map(r=>v(r))}async function b(e,r){let t=k(e,[]),n={};t.algo&&(n.algo=t.algo),t.pointer&&(n.pointer=t.pointer);let a=await w("io",n,r);if(!a||typeof a!="object")throw new l("Invalid IO response structure",void 0,{context:{response:a,definition:e}});if(!a||typeof a!="object")throw new l("Invalid IO response structure",void 0,{context:{response:a,definition:e}});let o=E(a,{deep:!0});return{inputs:o.inputs,outputs:o.outputs}}async function C(e,r){A("fetchParsedDefinitionIO",r.suppressClientSideWarning);let{inputs:t,outputs:n}=await b(e,r);return{inputs:D(t),outputs:n}}var S=class e{constructor(r){d(this,"innerTree");d(this,"paramName");this.paramName=r,this.innerTree={}}append(r,t){let n=e.formatPathString(r);this.innerTree[n]||(this.innerTree[n]=[]);let a=t.map(o=>({data:e.serializeValue(o)}));return this.innerTree[n].push(...a),this}appendSingle(r,t){return this.append(r,[t])}fromDataTreeDefault(r){this.innerTree={};for(let[t,n]of Object.entries(r)){if(!Array.isArray(n))continue;let a=e.parsePathString(t);this.append(a,n)}return this}appendFlat(r){let t=Array.isArray(r)?r:[r];return this.append([0],t)}flatten(){let r=[];for(let t of Object.values(this.innerTree))if(Array.isArray(t))for(let n of t)r.push(e.deserializeValue(n.data));return r}getPaths(){return Object.keys(this.innerTree)}getPath(r){let t=e.formatPathString(r),n=this.innerTree[t];if(n)return n.map(a=>e.deserializeValue(a.data))}toComputeFormat(){return{ParamName:this.paramName,InnerTree:this.innerTree}}getInnerTree(){return this.innerTree}getParamName(){return this.paramName}static fromInputParams(r){return r.filter(t=>e.hasValidValue(t.default)).map(t=>{let n=new e(t.nickname||"unnamed"),a=t.default;if(t.treeAccess&&e.isDataTreeStructure(a))n.fromDataTreeDefault(a),e.isNumericInput(t)&&n.applyNumericConstraints(t.minimum,t.maximum,t.nickname||"unnamed");else{let o=Array.isArray(a)?a:[a],s=e.processValues(o,t);n.appendFlat(s)}return n.toComputeFormat()})}static fromInputParam(r){return e.hasValidValue(r.default)?e.fromInputParams([r])[0]:void 0}static replaceTreeValue(r,t,n){if(r.length>0&&r[0]instanceof e){let o=r,s=o.findIndex(u=>u.getParamName()===t),i=new e(t);return typeof n=="object"&&n!==null&&!Array.isArray(n)&&e.isDataTreeStructure(n)?i.fromDataTreeDefault(n):(Array.isArray(n),i.appendFlat(n)),s!==-1?o[s]=i:o.push(i),o}else{let o=r,s=o.findIndex(p=>p.ParamName===t),i=new e(t);typeof n=="object"&&n!==null&&!Array.isArray(n)&&e.isDataTreeStructure(n)?i.fromDataTreeDefault(n):(Array.isArray(n),i.appendFlat(n));let u=i.toComputeFormat();return s!==-1?o[s]=u:o.push(u),o}}static getTreeValue(r,t){if(r.length>0&&r[0]instanceof e){let o=r.find(i=>i.getParamName()===t);if(!o)return null;let s=o.flatten();return s.length===0?null:s.length===1?s[0]:s}else{let o=r.find(p=>p.ParamName===t);if(!o)return null;let s=o.InnerTree;if(!s)return null;let i=Object.keys(s)[0];if(!i)return null;let u=s[i];if(Array.isArray(u)){if(u.length===1){let p=u[0]?.data;return p!==void 0?e.deserializeValue(p):null}return u.map(p=>p?.data!==void 0?e.deserializeValue(p.data):null).filter(p=>p!==null)}return u?.data!==void 0?e.deserializeValue(u.data):u}}static parsePathString(r){let t=r.match(/^\{([\d;]+)\}$/);return t?t[1].split(";").map(Number):(c().warn(`Invalid TreeBuilder path format: ${r}, using [0]`),[0])}static formatPathString(r){return`{${r.join(";")}}`}applyNumericConstraints(r,t,n){for(let a of Object.values(this.innerTree))if(Array.isArray(a))for(let o of a){let s=e.deserializeValue(o.data);if(typeof s=="number"){let i=e.clampValue(s,r,t,n);o.data=e.serializeValue(i)}}}static serializeValue(r){return typeof r=="boolean"||typeof r=="number"||typeof r=="string"?r:typeof r=="object"&&r!==null?JSON.stringify(r):String(r)}static deserializeValue(r){if(typeof r=="boolean"||typeof r=="number"||typeof r!="string")return r;if(r.startsWith("{")||r.startsWith("["))try{return JSON.parse(r)}catch{return r}return isNaN(Number(r))?r==="true"?!0:r==="false"?!1:r:Number(r)}static hasValidValue(r){return r==null?!1:typeof r=="string"?!0:!(Array.isArray(r)&&r.length===0||typeof r=="object"&&!Array.isArray(r)&&Object.keys(r).length===0)}static isDataTreeStructure(r){return typeof r!="object"||r===null||Array.isArray(r)?!1:Object.entries(r).every(([t,n])=>typeof t=="string"&&/^\{[\d;]+\}$/.test(t)&&Array.isArray(n))}static isNumericInput(r){return r.paramType==="Number"||r.paramType==="Integer"}static processValues(r,t){return r.map(n=>e.isNumericInput(t)&&typeof n=="number"?e.clampValue(n,t.minimum,t.maximum,t.nickname||"unnamed"):n).filter(n=>n!=null)}static clampValue(r,t,n,a){let o=r;return t!=null&&o<t&&(c().warn(`${a}: ${r} below min ${t}, clamping`),o=t),n!=null&&o>n&&(c().warn(`${a}: ${r} above max ${n}, clamping`),o=n),o}};export{T as a,$ as b,R as c,x as d,P as e,v as f,D as g,b as h,C as i,S as j};
|
|
2
|
+
//# sourceMappingURL=chunk-I3OX3G7J.js.map
|