selva-compute 1.1.0 → 1.1.2
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 +71 -10
- package/dist/{base-DbB0Ggdq.d.cts → base-dtik4Dlu.d.cts} +20 -0
- package/dist/{base-DbB0Ggdq.d.ts → base-dtik4Dlu.d.ts} +20 -0
- package/dist/chunk-F7DPIDIA.cjs +2 -0
- package/dist/{chunk-G6W5VE7C.cjs.map → chunk-F7DPIDIA.cjs.map} +1 -1
- package/dist/chunk-FMFP7GIM.js +2 -0
- package/dist/chunk-FMFP7GIM.js.map +1 -0
- package/dist/chunk-MK3M76VN.js +3 -0
- package/dist/chunk-MK3M76VN.js.map +1 -0
- package/dist/chunk-PE2FMBXD.cjs +3 -0
- package/dist/chunk-PE2FMBXD.cjs.map +1 -0
- package/dist/{chunk-M2HPEWXH.cjs → chunk-QCHPQ22Y.cjs} +2 -2
- package/dist/{chunk-M2HPEWXH.cjs.map → chunk-QCHPQ22Y.cjs.map} +1 -1
- package/dist/{chunk-QFHFH5BS.js → chunk-WD3ENUAA.js} +2 -2
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +10 -10
- package/dist/core.d.ts +10 -10
- package/dist/core.js +1 -1
- package/dist/grasshopper.cjs +1 -1
- package/dist/grasshopper.d.cts +9 -6
- package/dist/grasshopper.d.ts +9 -6
- package/dist/grasshopper.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{schemas-CQEJ5EZy.d.ts → schemas-BE5ai7jG.d.cts} +17 -4
- package/dist/{schemas-CQEJ5EZy.d.cts → schemas-BE5ai7jG.d.ts} +17 -4
- 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 +1 -2
- package/dist/chunk-FNWG34KH.cjs +0 -3
- package/dist/chunk-FNWG34KH.cjs.map +0 -1
- package/dist/chunk-G6W5VE7C.cjs +0 -2
- package/dist/chunk-I3OX3G7J.js +0 -2
- package/dist/chunk-I3OX3G7J.js.map +0 -1
- package/dist/chunk-VGM4KAFN.js +0 -3
- package/dist/chunk-VGM4KAFN.js.map +0 -1
- /package/dist/{chunk-QFHFH5BS.js.map → chunk-WD3ENUAA.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# selva-compute
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An intermediate-level TypeScript framework for building web applications with Rhino Compute and Grasshopper.
|
|
4
4
|
|
|
5
5
|
`selva-compute` simplifies the process of communicating with Rhino Compute, handling Grasshopper definitions, and visualizing results in the browser with Three.js.
|
|
6
6
|
|
|
@@ -12,21 +12,82 @@ npm install selva-compute three
|
|
|
12
12
|
|
|
13
13
|
_(Note: `three` is a peer dependency if you use the visualization features)_
|
|
14
14
|
|
|
15
|
+
## Why this project exists
|
|
16
|
+
|
|
17
|
+
`selva-compute` provides a type-safe, production-ready foundation for building with Rhino Compute:
|
|
18
|
+
|
|
19
|
+
- **Type-safe API** – Full TypeScript support with advanced error handling for stability
|
|
20
|
+
- **High-level abstractions** – Use `GrasshopperClient` and `GrasshopperResponseProcessor` to get started quickly
|
|
21
|
+
- **Ready-to-use visualization** – Integrated Three.js setup with `initScene()` and configurable rendering options
|
|
22
|
+
|
|
23
|
+
Whether you're building a simple solver or a complex web application, `selva-compute` handles the complexity so you can focus on your Grasshopper definitions.
|
|
24
|
+
|
|
25
|
+
> **Note:** The library currently focuses on the Grasshopper endpoint but is designed to support other Rhino Compute endpoints in future releases.
|
|
26
|
+
|
|
27
|
+
### Example with GrasshopperClient
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// Configuration
|
|
31
|
+
const DEFINITION_FILE = 'my-definition.gh';
|
|
32
|
+
const COMPUTE_SERVER = 'http://localhost:6500';
|
|
33
|
+
const API_KEY = 'your-api-key';
|
|
34
|
+
|
|
35
|
+
const config = {
|
|
36
|
+
serverUrl: COMPUTE_SERVER,
|
|
37
|
+
apiKey: API_KEY
|
|
38
|
+
} as GrasshopperComputeConfig;
|
|
39
|
+
|
|
40
|
+
let client: GrasshopperClient | null = null;
|
|
41
|
+
|
|
42
|
+
// Step 1: Create and initialize the client
|
|
43
|
+
client = await GrasshopperClient.create(config);
|
|
44
|
+
|
|
45
|
+
// Step 2: Get definition inputs and outputs
|
|
46
|
+
const io = await client.getIO(DEFINITION_FILE);
|
|
47
|
+
|
|
48
|
+
// Step 3: Build input data tree from definition parameters
|
|
49
|
+
const inputTree = TreeBuilder.fromInputParams(io.inputs);
|
|
50
|
+
|
|
51
|
+
// Step 4: Run the computation
|
|
52
|
+
const result = await client.solve(DEFINITION_FILE, inputTree);
|
|
53
|
+
|
|
54
|
+
// Step 5: Process and display results
|
|
55
|
+
const processor = new GrasshopperResponseProcessor(result);
|
|
56
|
+
const { values } = processor.getValues();
|
|
57
|
+
```
|
|
58
|
+
|
|
15
59
|
## Requirements
|
|
16
60
|
|
|
17
|
-
###
|
|
61
|
+
### Core Requirements
|
|
62
|
+
|
|
63
|
+
- **Node.js** >= 20
|
|
64
|
+
- **three** >= 0.179.0 (required for visualization features)
|
|
65
|
+
|
|
66
|
+
### Rhino Compute Compatibility
|
|
67
|
+
|
|
68
|
+
`selva-compute` works with both standard Rhino Compute and enhanced versions:
|
|
69
|
+
|
|
70
|
+
**Standard Rhino Compute** – The [official McNeel repository](https://github.com/mcneel/compute.rhino3d) works for basic Grasshopper solving with core features.
|
|
71
|
+
|
|
72
|
+
**Enhanced Setup** (Recommended) – Unlock advanced features:
|
|
73
|
+
|
|
74
|
+
1. **Selva Rhino Plugin** – Grasshopper plugin that simplifies building Three.js visualizations and exporting results directly from Grasshopper. [Download from Food4Rhino](https://www.food4rhino.com/en/app/selva?lang=en). Detailed documentation will be available when the Selva project is open-sourced.
|
|
75
|
+
2. **Custom Compute Server** – Our [custom branch](https://github.com/VektorNode/compute.rhino3d) enables:
|
|
76
|
+
- **Input Grouping** – Organize inputs with the `groupName` property
|
|
77
|
+
- **Persistent IDs** – Uniquely identify inputs across definition changes using Grasshopper object GUIDs
|
|
78
|
+
|
|
79
|
+
> Features requiring the enhanced setup will be clearly marked in the documentation.
|
|
18
80
|
|
|
19
|
-
|
|
81
|
+
## Acknowledgement
|
|
20
82
|
|
|
21
|
-
|
|
22
|
-
2. **Custom Compute Server** (Optional): Standard Rhino Compute works for basic solving. However, our **[custom branch](https://github.com/VektorNode/compute.rhino3d)** is required if you want to use:
|
|
23
|
-
- **Input Grouping**: Support for the `groupName` property in parameters.
|
|
24
|
-
- **Persistent IDs**: Support for the `id` property to uniquely identify inputs across definition changes.
|
|
83
|
+
This library is built on production experience and draws from several official McNeel repositories. Where code has been adapted, it is clearly marked in the relevant files.
|
|
25
84
|
|
|
26
|
-
|
|
85
|
+
**Key References:**
|
|
27
86
|
|
|
28
|
-
-
|
|
29
|
-
-
|
|
87
|
+
- [compute.rhino3d.appserver](https://github.com/mcneel/compute.rhino3d.appserver) – Server implementation reference
|
|
88
|
+
- [IO/Schema.cs](https://github.com/mcneel/compute.rhino3d/blob/8.x/src/compute.geometry/IO/Schema.cs) – Grasshopper API structure
|
|
89
|
+
- [GrasshopperDefinition.cs](https://github.com/mcneel/compute.rhino3d/blob/8.x/src/compute.geometry/GrasshopperDefinition.cs) – Definition parsing logic
|
|
90
|
+
- [computeclient_js](https://github.com/mcneel/computeclient_js) – JavaScript client implementation
|
|
30
91
|
|
|
31
92
|
## License
|
|
32
93
|
|
|
@@ -113,6 +113,26 @@ declare class RhinoComputeError extends Error {
|
|
|
113
113
|
context?: Record<string, unknown>;
|
|
114
114
|
originalError?: Error;
|
|
115
115
|
});
|
|
116
|
+
/**
|
|
117
|
+
* Create a generic validation error with custom reason
|
|
118
|
+
*/
|
|
119
|
+
static validation(inputName: string, reason: string, context?: Record<string, unknown>): RhinoComputeError;
|
|
120
|
+
/**
|
|
121
|
+
* Create an error for missing/empty values
|
|
122
|
+
*/
|
|
123
|
+
static missingValues(inputName: string, expectedType?: string, context?: Record<string, unknown>): RhinoComputeError;
|
|
124
|
+
/**
|
|
125
|
+
* Create an error for invalid default value in value list
|
|
126
|
+
*/
|
|
127
|
+
static invalidDefault(inputName: string, defaultValue: unknown, availableValues: unknown[], context?: Record<string, unknown>): RhinoComputeError;
|
|
128
|
+
/**
|
|
129
|
+
* Create an error for unknown parameter type
|
|
130
|
+
*/
|
|
131
|
+
static unknownParamType(paramType: string, paramName?: string, context?: Record<string, unknown>): RhinoComputeError;
|
|
132
|
+
/**
|
|
133
|
+
* Create an error for invalid input structure
|
|
134
|
+
*/
|
|
135
|
+
static invalidStructure(inputName: string, expectedStructure: string, context?: Record<string, unknown>): RhinoComputeError;
|
|
116
136
|
}
|
|
117
137
|
|
|
118
138
|
export { ComputeServerStats as C, RhinoComputeError as R };
|
|
@@ -113,6 +113,26 @@ declare class RhinoComputeError extends Error {
|
|
|
113
113
|
context?: Record<string, unknown>;
|
|
114
114
|
originalError?: Error;
|
|
115
115
|
});
|
|
116
|
+
/**
|
|
117
|
+
* Create a generic validation error with custom reason
|
|
118
|
+
*/
|
|
119
|
+
static validation(inputName: string, reason: string, context?: Record<string, unknown>): RhinoComputeError;
|
|
120
|
+
/**
|
|
121
|
+
* Create an error for missing/empty values
|
|
122
|
+
*/
|
|
123
|
+
static missingValues(inputName: string, expectedType?: string, context?: Record<string, unknown>): RhinoComputeError;
|
|
124
|
+
/**
|
|
125
|
+
* Create an error for invalid default value in value list
|
|
126
|
+
*/
|
|
127
|
+
static invalidDefault(inputName: string, defaultValue: unknown, availableValues: unknown[], context?: Record<string, unknown>): RhinoComputeError;
|
|
128
|
+
/**
|
|
129
|
+
* Create an error for unknown parameter type
|
|
130
|
+
*/
|
|
131
|
+
static unknownParamType(paramType: string, paramName?: string, context?: Record<string, unknown>): RhinoComputeError;
|
|
132
|
+
/**
|
|
133
|
+
* Create an error for invalid input structure
|
|
134
|
+
*/
|
|
135
|
+
static invalidStructure(inputName: string, expectedStructure: string, context?: Record<string, unknown>): RhinoComputeError;
|
|
116
136
|
}
|
|
117
137
|
|
|
118
138
|
export { ComputeServerStats as C, RhinoComputeError as R };
|
|
@@ -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 _chunkQCHPQ22Ycjs = require('./chunk-QCHPQ22Y.cjs');var _chunkPE2FMBXDcjs = require('./chunk-PE2FMBXD.cjs');_chunkPE2FMBXDcjs.h.call(void 0, );_chunkPE2FMBXDcjs.f.call(void 0, );_chunkPE2FMBXDcjs.l.call(void 0, );var T=class e{constructor(r){_chunkPE2FMBXDcjs.c.call(void 0, this,"config");_chunkPE2FMBXDcjs.c.call(void 0, this,"serverStats");_chunkPE2FMBXDcjs.c.call(void 0, this,"disposed",!1);this.config=this.normalizeComputeConfig(r),this.serverStats=new (0, _chunkPE2FMBXDcjs.n)(this.config.serverUrl,this.config.apiKey)}static async create(r){let t=new e(r);if(!await t.serverStats.isServerOnline())throw new (0, _chunkPE2FMBXDcjs.e)("Rhino Compute server is not online",_chunkPE2FMBXDcjs.d.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, _chunkPE2FMBXDcjs.e)("Definition URL/content is required",_chunkPE2FMBXDcjs.d.INVALID_INPUT,{context:{receivedUrl:r}});if(r instanceof Uint8Array&&r.length===0)throw new (0, _chunkPE2FMBXDcjs.e)("Definition content is empty",_chunkPE2FMBXDcjs.d.INVALID_INPUT);if(!await this.serverStats.isServerOnline())throw new (0, _chunkPE2FMBXDcjs.e)("Rhino Compute server is not online",_chunkPE2FMBXDcjs.d.NETWORK_ERROR,{context:{serverUrl:this.config.serverUrl}});let a=await P(t,r,this.config);if(a&&typeof a=="object"&&"message"in a&&!("fileData"in a))throw new (0, _chunkPE2FMBXDcjs.e)(a.message||"Computation failed",_chunkPE2FMBXDcjs.d.COMPUTATION_ERROR,{context:{definition:typeof r=="string"&&r.length<200?r:"...content...",inputs:t}});return a}catch(a){throw this.config.debug&&_chunkPE2FMBXDcjs.i.call(void 0, ).error("Compute failed:",a),a instanceof _chunkPE2FMBXDcjs.e?a:new (0, _chunkPE2FMBXDcjs.e)(a instanceof Error?a.message:String(a),_chunkPE2FMBXDcjs.d.COMPUTATION_ERROR,{context:{definition:typeof r=="string"&&r.length<200?r:"...content...",inputs:t},originalError:a instanceof Error?a:new Error(String(a))})}}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, _chunkPE2FMBXDcjs.e)("GrasshopperClient has been disposed and cannot be used",_chunkPE2FMBXDcjs.d.INVALID_STATE)}normalizeComputeConfig(r){if(!_optionalChain([r, 'access', _4 => _4.serverUrl, 'optionalAccess', _5 => _5.trim, 'call', _6 => _6()]))throw new (0, _chunkPE2FMBXDcjs.e)("serverUrl is required",_chunkPE2FMBXDcjs.d.INVALID_CONFIG,{context:{receivedServerUrl:r.serverUrl}});try{new URL(r.serverUrl)}catch (e2){throw new (0, _chunkPE2FMBXDcjs.e)("serverUrl must be a valid URL",_chunkPE2FMBXDcjs.d.INVALID_CONFIG,{context:{receivedServerUrl:r.serverUrl}})}if(r.serverUrl===""||r.serverUrl==="https://compute.rhino3d.com/")throw new (0, _chunkPE2FMBXDcjs.e)("serverUrl must be set to your Compute server URL. The default public endpoint is not allowed.",_chunkPE2FMBXDcjs.d.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 B=async(e,r=null)=>{try{return await K(e,r)}catch(t){throw new (0, _chunkPE2FMBXDcjs.e)("Failed to extract files from compute response",_chunkPE2FMBXDcjs.d.INVALID_STATE,{context:{originalError:t instanceof Error?t.message:String(t)},originalError:t instanceof Error?t:void 0})}},S= exports.c =async(e,r,t=null)=>{if(typeof document>"u"||typeof Blob>"u")throw new (0, _chunkPE2FMBXDcjs.e)("File download functionality is only available in browser environments. This function requires the DOM API (document, Blob).",_chunkPE2FMBXDcjs.d.BROWSER_ONLY,{context:{environment:typeof window<"u"?"browser (SSR)":"Node.js",documentAvailable:typeof document<"u",blobAvailable:typeof Blob<"u"}});try{let a=await K(e,t);await ie(a,r)}catch(a){throw a instanceof _chunkPE2FMBXDcjs.e?a:new (0, _chunkPE2FMBXDcjs.e)("Failed to download files from compute response",_chunkPE2FMBXDcjs.d.INVALID_STATE,{context:{originalError:a instanceof Error?a.message:String(a)},originalError:a instanceof Error?a:void 0})}},K=async(e,r)=>{let t=[];if(e.forEach(a=>{let n=`${a.fileName}${a.fileType}`;if(a.subFolder&&a.subFolder.trim()!==""&&(n=`${a.subFolder}/${n}`),a.isBase64Encoded===!0&&a.data){let s=_chunkQCHPQ22Ycjs.c.call(void 0, a.data);t.push({fileName:`${a.fileName}${a.fileType}`,content:new Uint8Array(s.buffer),path:n})}else a.isBase64Encoded===!1&&a.data&&t.push({fileName:`${a.fileName}${a.fileType}`,content:a.data,path:n})}),r){let a=Array.isArray(r)?r:[r],n=await Promise.all(a.map(async s=>{try{let o=await fetch(s.filePath);if(!o.ok)return _chunkPE2FMBXDcjs.i.call(void 0, ).warn(`Failed to fetch additional file from URL: ${s.filePath}`),null;let u=await(await o.blob()).arrayBuffer();return{fileName:s.fileName,content:new Uint8Array(u),path:s.fileName}}catch(o){return _chunkPE2FMBXDcjs.i.call(void 0, ).error(`Error fetching additional file from URL: ${s.filePath}`,o),null}}));t.push(...n.filter(s=>s!==null))}return t};async function ie(e,r){let{zipSync:t,strToU8:a}=await Promise.resolve().then(() => _interopRequireWildcard(require("fflate"))),n={};e.forEach(i=>{n[i.path]=typeof i.content=="string"?a(i.content):i.content});let s=t(n,{level:6}),o=new Blob([s],{type:"application/zip"});ue(o,`${r}.zip`)}function ue(e,r){if(typeof document>"u")throw new (0, _chunkPE2FMBXDcjs.e)("saveFile requires a browser environment with DOM API access.",_chunkPE2FMBXDcjs.d.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 F=new Map;function Y(e,r){F.set(e,r)}Y("Rhino.Geometry.Point3d",(e,r)=>{let t=r;return!t||typeof t.X!="number"?null:new e.Point([t.X,t.Y,t.Z])});Y("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 le(e){if(F.has(e))return F.get(e);for(let[r,t]of F)if(e.startsWith(r))return t}function pe(e){return!e||typeof e!="object"?null:_nullishCoalesce(_nullishCoalesce(e.data, () => (e.value)), () => (null))}function J(e,r,t){let a=le(r);if(a)try{return a(t,e)}catch(n){_chunkPE2FMBXDcjs.i.call(void 0, ).warn(`Failed to decode Rhino type ${r}:`,n)}try{let n=pe(e);if(n)return t.CommonObject.decode(n)}catch(n){return _chunkPE2FMBXDcjs.i.call(void 0, ).warn(`Failed to decode ${r} with CommonObject:`,n),{__decodeError:!0,type:r,raw:e}}return e}var D={STRING:"System.String",INT:"System.Int32",DOUBLE:"System.Double",BOOL:"System.Boolean"},fe="Rhino.Geometry.",ce=["WebDisplay"],me="FileData";function de(e){return ce.some(r=>e.includes(r))}function X(e){if(typeof e!="string")return e;let r=e.trim();if(!(r.startsWith("{")||r.startsWith("[")||r.startsWith('"')))return e;try{let a=JSON.parse(r);if(typeof a=="string")try{return JSON.parse(a)}catch (e3){return a}return a}catch (e4){return e}}function ye(e,r,t){switch(r){case D.STRING:return typeof e!="string"?e:e.replace(/^"(.*)"$/,"$1");case D.INT:return Number.parseInt(e,10);case D.DOUBLE:return Number.parseFloat(e);case D.BOOL:return String(e).toLowerCase()==="true";default:return t&&r.startsWith(fe)?J(e,r,t):e}}function _(e,r,t,a){if(de(r))return null;if(typeof e!="string")return e;let n=t?X(e):e;return ye(n,r,a)}function V(e,r){for(let t of Object.values(e))if(Array.isArray(t))for(let a of t)r(a)}function Z(e,r=!1,t={}){let{parseValues:a=!0,rhino:n,stringOnly:s=!1}=t,o={};for(let i of e.values)V(i.InnerTree,u=>{if(s&&u.type!==D.STRING)return;let p=r?u.id:i.ParamName;if(!p)return;let m=_(u.data,u.type,a,n);o[p]===void 0?o[p]=m:Array.isArray(o[p])?o[p].push(m):o[p]=[o[p],m]});return{values:o}}function H(e){let r=[];for(let t of e.values)V(t.InnerTree,a=>{if(!a.type.includes(me))return;let n=X(a.data);n&&n.FileName&&n.FileType&&n.Data&&r.push(n)});return r}function U(e,r,t={}){let{parseValues:a=!0,rhino:n,stringOnly:s=!1}=t,o;if("byName"in r?o=e.values.find(u=>u.ParamName===r.byName):o=e.values.find(u=>{let p=!1;return V(u.InnerTree,m=>{m.id===r.byId&&(p=!0)}),p}),!o)return;let i=[];if(V(o.InnerTree,u=>{if("byId"in r&&u.id!==r.byId||s&&u.type!==D.STRING)return;let p=_(u.data,u.type,a,n);i.push(p)}),i.length!==0)return i.length===1?i[0]:i}var I=class{constructor(r,t=!1){this.response=r;this.debug=t}getValues(r=!1,t={}){return Z(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:a}=await Promise.resolve().then(() => _interopRequireWildcard(require("./visualization.cjs")));return a(this.response,t)}catch(a){let{RhinoComputeError:n,ErrorCodes:s}=(_chunkPE2FMBXDcjs.h.call(void 0, ),_chunkPE2FMBXDcjs.b.call(void 0, _chunkPE2FMBXDcjs.g));throw new n("Failed to load three.js visualization module. Ensure three.js is installed as a peer dependency.",s.INVALID_STATE,{context:{originalError:a instanceof Error?a.message:String(a)}})}}getFileData(){return H(this.response)}getAndDownloadFiles(r,t){let a=this.getFileData();S(a,r,t)}};_chunkPE2FMBXDcjs.l.call(void 0, );function w(e,r){r||typeof window<"u"&&_chunkPE2FMBXDcjs.i.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&&w("solveGrasshopperDefinition",t.suppressClientSideWarning);let a=M(r,e);he(a,t);let n=await _chunkPE2FMBXDcjs.m.call(void 0, "grasshopper",a,t);return"pointer"in n&&delete n.pointer,n}function M(e,r){let t={algo:null,pointer:null,values:r};return e instanceof Uint8Array?t.algo=_chunkQCHPQ22Ycjs.d.call(void 0, e):e.startsWith("http")?t.pointer=e:_chunkQCHPQ22Ycjs.b.call(void 0, e)?t.algo=e:t.algo=_chunkQCHPQ22Ycjs.a.call(void 0, e),t}function he(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)}function ge(e,r={}){let{preserveSpaces:t=!1}=r,a=e.trim();return t?(a=a.charAt(0).toLowerCase()+a.slice(1).replace(/[-_](.)/g,(n,s)=>s?s.toUpperCase():""),a):(a=a.replace(/^[A-Z]/,n=>n.toLowerCase()).replace(/[\s-_]+(.)?/g,(n,s)=>s?s.toUpperCase():""),a)}function A(e,r={}){return!e||typeof e!="object"?e:Array.isArray(e)?r.deep?e.map(t=>A(t,r)):e:Object.keys(e).reduce((t,a)=>{let n=ge(a,{preserveSpaces:r.preserveSpaces}),s=e[a];return t[n]=r.deep?A(s,r):s,t},{})}_chunkPE2FMBXDcjs.h.call(void 0, );function Q(e){if(typeof e.default!="object"||e.default===null)return;if(!("innerTree"in e.default)){_chunkPE2FMBXDcjs.i.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 a={};for(let[n,s]of Object.entries(r))a[n]=s.map(o=>{if(typeof o.data=="string"){if(o.type==="System.Double"||o.type==="System.Int32"){let i=Number(o.data);return Number.isNaN(i)?o.data:i}if(o.type==="System.Boolean")return o.data.toLowerCase()==="true";if(o.type.startsWith("Rhino.Geometry")||o.type==="System.String")try{return JSON.parse(o.data)}catch (e5){return o.data}}return o.data});e.default=a;return}let t=[];for(let a of Object.values(r))Array.isArray(a)&&a.forEach(n=>{n&&typeof n=="object"&&"data"in n&&t.push(n.data)});t.length===0?e.default=void 0:t.length===1?e.default=t[0]:e.default=t}_chunkPE2FMBXDcjs.h.call(void 0, );function G(e,r){let{transform:t,setUndefinedOnEmpty:a=!0}=r;if(!(e.default===void 0||e.default===null))if(Array.isArray(e.default)){let n=e.default.map(t).filter(s=>s!==null);e.default=n.length>0?n:void 0}else{let n=t(e.default);n!==null?e.default=n:a&&(e.default=void 0)}}function Te(){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 be(){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 Ie(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:(_chunkPE2FMBXDcjs.i.call(void 0, ).warn(`Parsed value for input ${e} is not an object`),null)}catch(t){return _chunkPE2FMBXDcjs.i.call(void 0, ).warn(`Failed to parse object value "${r}" for input ${e}`,t),null}return null}}function ee(e,r,t){let a=Number(e.toFixed(r));return Math.abs(e-a)<t?a:e}function xe(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),k=Number(g.toFixed(h));return Math.abs(k-g)<r?k:g}return 1}let a=String(e),n=a.toLowerCase().match(/e(-?\d+)/);if(n){let E=Number(n[1]);if(E<0||a.toLowerCase().includes("e-")){let y=Math.abs(E),h=Math.pow(10,-y),g=Number(h.toFixed(y));return Math.abs(g-h)<r?g:h}return .1}let s=12,i=t.toFixed(s).replace(/0+$/,""),u=Math.min((i.split(".")[1]||"").length,s);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 re(e,r=1e-8){let t=e.paramType==="Integer";if(G(e,{transform:Te()}),t){Array.isArray(e.default)?e.default=e.default.map(s=>typeof s=="number"?Math.round(s):s):typeof e.default=="number"&&(e.default=Math.round(e.default)),e.stepSize=1;return}let a=Array.isArray(e.default)?e.default[0]:e.default,n;if(typeof a=="number"&&Number.isFinite(a)&&a!==0?n=a:typeof e.minimum=="number"&&Number.isFinite(e.minimum)&&e.minimum!==0?n=e.minimum:typeof e.maximum=="number"&&Number.isFinite(e.maximum)&&e.maximum!==0&&(n=e.maximum),n!==void 0?e.stepSize=xe(n,r):e.stepSize=.1,typeof e.stepSize=="number"){let s=0,o=String(e.stepSize),i=o.toLowerCase().match(/e(-?\d+)/);if(i?s=Math.abs(Number(i[1])):s=_nullishCoalesce(_optionalChain([o, 'access', _7 => _7.split, 'call', _8 => _8("."), 'access', _9 => _9[1], 'optionalAccess', _10 => _10.length]), () => (0)),s===0&&typeof a=="number"&&a!==0&&Math.abs(a)<1){let u=Math.ceil(-Math.log10(Math.abs(a)));Number.isFinite(u)&&u>0&&(s=u)}s=Math.min(Math.max(s,0),12),Array.isArray(e.default)?e.default=e.default.map(u=>typeof u=="number"?ee(u,s,r):u):typeof e.default=="number"&&(e.default=ee(e.default,s,r))}}function Pe(e){try{G(e,{transform:be(),setUndefinedOnEmpty:!1})}catch(r){throw r instanceof Error?new (0, _chunkPE2FMBXDcjs.e)(r.message):r}}function Ce(e){G(e,{transform:De(),setUndefinedOnEmpty:!1})}function te(e){G(e,{transform:Ie(e.nickname||"unnamed"),setUndefinedOnEmpty:!0})}function Se(e){if(!e.values||typeof e.values!="object"||Object.keys(e.values).length===0)throw _chunkPE2FMBXDcjs.e.missingValues(e.nickname||"unnamed","ValueList");if(e.default!==void 0&&e.default!==null){let r=String(e.default).toLowerCase();Object.keys(e.values).some(a=>a.toLowerCase()===r)||_chunkPE2FMBXDcjs.i.call(void 0, ).warn(`ValueList input "${e.nickname||"unnamed"}" default value "${e.default}" is not in available values`)}}var ae={Number:re,Integer:re,Boolean:Pe,Text:Ce,ValueList:Se,Geometry:te,File:te};_chunkPE2FMBXDcjs.l.call(void 0, );function Re(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 R(e){let r={description:e.description,name:e.name,nickname:e.nickname,treeAccess:e.treeAccess,groupName:_nullishCoalesce(e.groupName, () => ("")),id:e.id};try{Q(e);let t=ae[e.paramType];if(!t)throw _chunkPE2FMBXDcjs.e.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 _chunkPE2FMBXDcjs.e.unknownParamType(e.paramType,e.name)}}catch(t){if(t instanceof _chunkPE2FMBXDcjs.e)return _chunkPE2FMBXDcjs.i.call(void 0, ).error(`Validation error for input ${e.name||"unknown"}:`,t.message),Re(e,r);throw new (0, _chunkPE2FMBXDcjs.e)(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 x(e){return e.map(r=>R(r))}async function b(e,r){let t=M(e,[]),a={};t.algo&&(a.algo=t.algo),t.pointer&&(a.pointer=t.pointer);let n=await _chunkPE2FMBXDcjs.m.call(void 0, "io",a,r);if(!n||typeof n!="object")throw new (0, _chunkPE2FMBXDcjs.e)("Invalid IO response structure",_chunkPE2FMBXDcjs.d.INVALID_INPUT,{context:{response:n,definition:e}});let s=A(n,{deep:!0});return{inputs:s.inputs,outputs:s.outputs}}async function C(e,r){w("fetchParsedDefinitionIO",r.suppressClientSideWarning);let{inputs:t,outputs:a}=await b(e,r);return{inputs:x(t),outputs:a}}var v=class e{constructor(r){_chunkPE2FMBXDcjs.c.call(void 0, this,"innerTree");_chunkPE2FMBXDcjs.c.call(void 0, this,"paramName");this.paramName=r,this.innerTree={}}append(r,t){let a=e.formatPathString(r);this.innerTree[a]||(this.innerTree[a]=[]);let n=t.map(s=>({data:e.serializeValue(s)}));return this.innerTree[a].push(...n),this}appendSingle(r,t){return this.append(r,[t])}fromDataTreeDefault(r){this.innerTree={};for(let[t,a]of Object.entries(r)){if(!Array.isArray(a))continue;let n=e.parsePathString(t);this.append(n,a)}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 a of t)r.push(e.deserializeValue(a.data));return r}getPaths(){return Object.keys(this.innerTree)}getPath(r){let t=e.formatPathString(r),a=this.innerTree[t];if(a)return a.map(n=>e.deserializeValue(n.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 a=new e(t.nickname||"unnamed"),n=t.default;if(t.treeAccess&&e.isDataTreeStructure(n))a.fromDataTreeDefault(n),e.isNumericInput(t)&&a.applyNumericConstraints(t.minimum,t.maximum,t.nickname||"unnamed");else{let s=Array.isArray(n)?n:[n],o=e.processValues(s,t);a.appendFlat(o)}return a.toComputeFormat()})}static fromInputParam(r){return e.hasValidValue(r.default)?e.fromInputParams([r])[0]:void 0}static replaceTreeValue(r,t,a){if(r.length>0&&r[0]instanceof e){let s=r,o=s.findIndex(u=>u.getParamName()===t),i=new e(t);return typeof a=="object"&&a!==null&&!Array.isArray(a)&&e.isDataTreeStructure(a)?i.fromDataTreeDefault(a):(Array.isArray(a),i.appendFlat(a)),o!==-1?s[o]=i:s.push(i),s}else{let s=r,o=s.findIndex(p=>p.ParamName===t),i=new e(t);typeof a=="object"&&a!==null&&!Array.isArray(a)&&e.isDataTreeStructure(a)?i.fromDataTreeDefault(a):(Array.isArray(a),i.appendFlat(a));let u=i.toComputeFormat();return o!==-1?s[o]=u:s.push(u),s}}static getTreeValue(r,t){if(r.length>0&&r[0]instanceof e){let s=r.find(i=>i.getParamName()===t);if(!s)return null;let o=s.flatten();return o.length===0?null:o.length===1?o[0]:o}else{let s=r.find(p=>p.ParamName===t);if(!s)return null;let o=s.InnerTree;if(!o)return null;let i=Object.keys(o)[0];if(!i)return null;let u=o[i];if(Array.isArray(u)){if(u.length===1){let p=_optionalChain([u, 'access', _11 => _11[0], 'optionalAccess', _12 => _12.data]);return p!==void 0?e.deserializeValue(p):null}return u.map(p=>_optionalChain([p, 'optionalAccess', _13 => _13.data])!==void 0?e.deserializeValue(p.data):null).filter(p=>p!==null)}return _optionalChain([u, 'optionalAccess', _14 => _14.data])!==void 0?e.deserializeValue(u.data):u}}static parsePathString(r){let t=r.match(/^\{([\d;]+)\}$/);return t?t[1].split(";").map(Number):(_chunkPE2FMBXDcjs.i.call(void 0, ).warn(`Invalid TreeBuilder path format: ${r}, using [0]`),[0])}static formatPathString(r){return`{${r.join(";")}}`}applyNumericConstraints(r,t,a){for(let n of Object.values(this.innerTree))if(Array.isArray(n))for(let s of n){let o=e.deserializeValue(s.data);if(typeof o=="number"){let i=e.clampValue(o,r,t,a);s.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,a])=>typeof t=="string"&&/^\{[\d;]+\}$/.test(t)&&Array.isArray(a))}static isNumericInput(r){return r.paramType==="Number"||r.paramType==="Integer"}static processValues(r,t){return r.map(a=>e.isNumericInput(t)&&typeof a=="number"?e.clampValue(a,t.minimum,t.maximum,t.nickname||"unnamed"):a).filter(a=>a!=null)}static clampValue(r,t,a,n){let s=r;return t!=null&&s<t&&(_chunkPE2FMBXDcjs.i.call(void 0, ).warn(`${n}: ${r} below min ${t}, clamping`),s=t),a!=null&&s>a&&(_chunkPE2FMBXDcjs.i.call(void 0, ).warn(`${n}: ${r} above max ${a}, clamping`),s=a),s}};exports.a = T; exports.b = B; exports.c = S; exports.d = I; exports.e = P; exports.f = R; exports.g = x; exports.h = b; exports.i = C; exports.j = v;
|
|
2
|
+
//# sourceMappingURL=chunk-F7DPIDIA.cjs.map
|
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/chunk-F7DPIDIA.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-F7DPIDIA.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 $,b as z,c as W,d as q}from"./chunk-WD3ENUAA.js";import{b as ne,c as d,d as c,e as l,f as se,g as oe,h as N,i as f,l as L,m as O,n as j}from"./chunk-MK3M76VN.js";N();se();L();var T=class e{constructor(r){d(this,"config");d(this,"serverStats");d(this,"disposed",!1);this.config=this.normalizeComputeConfig(r),this.serverStats=new j(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",c.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",c.INVALID_INPUT,{context:{receivedUrl:r}});if(r instanceof Uint8Array&&r.length===0)throw new l("Definition content is empty",c.INVALID_INPUT);if(!await this.serverStats.isServerOnline())throw new l("Rhino Compute server is not online",c.NETWORK_ERROR,{context:{serverUrl:this.config.serverUrl}});let a=await P(t,r,this.config);if(a&&typeof a=="object"&&"message"in a&&!("fileData"in a))throw new l(a.message||"Computation failed",c.COMPUTATION_ERROR,{context:{definition:typeof r=="string"&&r.length<200?r:"...content...",inputs:t}});return a}catch(a){throw this.config.debug&&f().error("Compute failed:",a),a instanceof l?a:new l(a instanceof Error?a.message:String(a),c.COMPUTATION_ERROR,{context:{definition:typeof r=="string"&&r.length<200?r:"...content...",inputs:t},originalError:a instanceof Error?a:new Error(String(a))})}}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",c.INVALID_STATE)}normalizeComputeConfig(r){if(!r.serverUrl?.trim())throw new l("serverUrl is required",c.INVALID_CONFIG,{context:{receivedServerUrl:r.serverUrl}});try{new URL(r.serverUrl)}catch{throw new l("serverUrl must be a valid URL",c.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.",c.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 B=async(e,r=null)=>{try{return await K(e,r)}catch(t){throw new l("Failed to extract files from compute response",c.INVALID_STATE,{context:{originalError:t instanceof Error?t.message:String(t)},originalError:t instanceof Error?t:void 0})}},S=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).",c.BROWSER_ONLY,{context:{environment:typeof window<"u"?"browser (SSR)":"Node.js",documentAvailable:typeof document<"u",blobAvailable:typeof Blob<"u"}});try{let a=await K(e,t);await ie(a,r)}catch(a){throw a instanceof l?a:new l("Failed to download files from compute response",c.INVALID_STATE,{context:{originalError:a instanceof Error?a.message:String(a)},originalError:a instanceof Error?a:void 0})}},K=async(e,r)=>{let t=[];if(e.forEach(a=>{let n=`${a.fileName}${a.fileType}`;if(a.subFolder&&a.subFolder.trim()!==""&&(n=`${a.subFolder}/${n}`),a.isBase64Encoded===!0&&a.data){let s=W(a.data);t.push({fileName:`${a.fileName}${a.fileType}`,content:new Uint8Array(s.buffer),path:n})}else a.isBase64Encoded===!1&&a.data&&t.push({fileName:`${a.fileName}${a.fileType}`,content:a.data,path:n})}),r){let a=Array.isArray(r)?r:[r],n=await Promise.all(a.map(async s=>{try{let o=await fetch(s.filePath);if(!o.ok)return f().warn(`Failed to fetch additional file from URL: ${s.filePath}`),null;let u=await(await o.blob()).arrayBuffer();return{fileName:s.fileName,content:new Uint8Array(u),path:s.fileName}}catch(o){return f().error(`Error fetching additional file from URL: ${s.filePath}`,o),null}}));t.push(...n.filter(s=>s!==null))}return t};async function ie(e,r){let{zipSync:t,strToU8:a}=await import("fflate"),n={};e.forEach(i=>{n[i.path]=typeof i.content=="string"?a(i.content):i.content});let s=t(n,{level:6}),o=new Blob([s],{type:"application/zip"});ue(o,`${r}.zip`)}function ue(e,r){if(typeof document>"u")throw new l("saveFile requires a browser environment with DOM API access.",c.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 F=new Map;function Y(e,r){F.set(e,r)}Y("Rhino.Geometry.Point3d",(e,r)=>{let t=r;return!t||typeof t.X!="number"?null:new e.Point([t.X,t.Y,t.Z])});Y("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 le(e){if(F.has(e))return F.get(e);for(let[r,t]of F)if(e.startsWith(r))return t}function pe(e){return!e||typeof e!="object"?null:e.data??e.value??null}function J(e,r,t){let a=le(r);if(a)try{return a(t,e)}catch(n){f().warn(`Failed to decode Rhino type ${r}:`,n)}try{let n=pe(e);if(n)return t.CommonObject.decode(n)}catch(n){return f().warn(`Failed to decode ${r} with CommonObject:`,n),{__decodeError:!0,type:r,raw:e}}return e}var D={STRING:"System.String",INT:"System.Int32",DOUBLE:"System.Double",BOOL:"System.Boolean"},fe="Rhino.Geometry.",ce=["WebDisplay"],me="FileData";function de(e){return ce.some(r=>e.includes(r))}function X(e){if(typeof e!="string")return e;let r=e.trim();if(!(r.startsWith("{")||r.startsWith("[")||r.startsWith('"')))return e;try{let a=JSON.parse(r);if(typeof a=="string")try{return JSON.parse(a)}catch{return a}return a}catch{return e}}function ye(e,r,t){switch(r){case D.STRING:return typeof e!="string"?e:e.replace(/^"(.*)"$/,"$1");case D.INT:return Number.parseInt(e,10);case D.DOUBLE:return Number.parseFloat(e);case D.BOOL:return String(e).toLowerCase()==="true";default:return t&&r.startsWith(fe)?J(e,r,t):e}}function _(e,r,t,a){if(de(r))return null;if(typeof e!="string")return e;let n=t?X(e):e;return ye(n,r,a)}function V(e,r){for(let t of Object.values(e))if(Array.isArray(t))for(let a of t)r(a)}function Z(e,r=!1,t={}){let{parseValues:a=!0,rhino:n,stringOnly:s=!1}=t,o={};for(let i of e.values)V(i.InnerTree,u=>{if(s&&u.type!==D.STRING)return;let p=r?u.id:i.ParamName;if(!p)return;let m=_(u.data,u.type,a,n);o[p]===void 0?o[p]=m:Array.isArray(o[p])?o[p].push(m):o[p]=[o[p],m]});return{values:o}}function H(e){let r=[];for(let t of e.values)V(t.InnerTree,a=>{if(!a.type.includes(me))return;let n=X(a.data);n&&n.FileName&&n.FileType&&n.Data&&r.push(n)});return r}function U(e,r,t={}){let{parseValues:a=!0,rhino:n,stringOnly:s=!1}=t,o;if("byName"in r?o=e.values.find(u=>u.ParamName===r.byName):o=e.values.find(u=>{let p=!1;return V(u.InnerTree,m=>{m.id===r.byId&&(p=!0)}),p}),!o)return;let i=[];if(V(o.InnerTree,u=>{if("byId"in r&&u.id!==r.byId||s&&u.type!==D.STRING)return;let p=_(u.data,u.type,a,n);i.push(p)}),i.length!==0)return i.length===1?i[0]:i}var I=class{constructor(r,t=!1){this.response=r;this.debug=t}getValues(r=!1,t={}){return Z(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:a}=await import("./visualization.js");return a(this.response,t)}catch(a){let{RhinoComputeError:n,ErrorCodes:s}=(N(),ne(oe));throw new n("Failed to load three.js visualization module. Ensure three.js is installed as a peer dependency.",s.INVALID_STATE,{context:{originalError:a instanceof Error?a.message:String(a)}})}}getFileData(){return H(this.response)}getAndDownloadFiles(r,t){let a=this.getFileData();S(a,r,t)}};L();function w(e,r){r||typeof window<"u"&&f().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&&w("solveGrasshopperDefinition",t.suppressClientSideWarning);let a=M(r,e);he(a,t);let n=await O("grasshopper",a,t);return"pointer"in n&&delete n.pointer,n}function M(e,r){let t={algo:null,pointer:null,values:r};return e instanceof Uint8Array?t.algo=q(e):e.startsWith("http")?t.pointer=e:z(e)?t.algo=e:t.algo=$(e),t}function he(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)}function ge(e,r={}){let{preserveSpaces:t=!1}=r,a=e.trim();return t?(a=a.charAt(0).toLowerCase()+a.slice(1).replace(/[-_](.)/g,(n,s)=>s?s.toUpperCase():""),a):(a=a.replace(/^[A-Z]/,n=>n.toLowerCase()).replace(/[\s-_]+(.)?/g,(n,s)=>s?s.toUpperCase():""),a)}function A(e,r={}){return!e||typeof e!="object"?e:Array.isArray(e)?r.deep?e.map(t=>A(t,r)):e:Object.keys(e).reduce((t,a)=>{let n=ge(a,{preserveSpaces:r.preserveSpaces}),s=e[a];return t[n]=r.deep?A(s,r):s,t},{})}N();function Q(e){if(typeof e.default!="object"||e.default===null)return;if(!("innerTree"in e.default)){f().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 a={};for(let[n,s]of Object.entries(r))a[n]=s.map(o=>{if(typeof o.data=="string"){if(o.type==="System.Double"||o.type==="System.Int32"){let i=Number(o.data);return Number.isNaN(i)?o.data:i}if(o.type==="System.Boolean")return o.data.toLowerCase()==="true";if(o.type.startsWith("Rhino.Geometry")||o.type==="System.String")try{return JSON.parse(o.data)}catch{return o.data}}return o.data});e.default=a;return}let t=[];for(let a of Object.values(r))Array.isArray(a)&&a.forEach(n=>{n&&typeof n=="object"&&"data"in n&&t.push(n.data)});t.length===0?e.default=void 0:t.length===1?e.default=t[0]:e.default=t}N();function G(e,r){let{transform:t,setUndefinedOnEmpty:a=!0}=r;if(!(e.default===void 0||e.default===null))if(Array.isArray(e.default)){let n=e.default.map(t).filter(s=>s!==null);e.default=n.length>0?n:void 0}else{let n=t(e.default);n!==null?e.default=n:a&&(e.default=void 0)}}function Te(){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 be(){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 Ie(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:(f().warn(`Parsed value for input ${e} is not an object`),null)}catch(t){return f().warn(`Failed to parse object value "${r}" for input ${e}`,t),null}return null}}function ee(e,r,t){let a=Number(e.toFixed(r));return Math.abs(e-a)<t?a:e}function xe(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),k=Number(g.toFixed(h));return Math.abs(k-g)<r?k:g}return 1}let a=String(e),n=a.toLowerCase().match(/e(-?\d+)/);if(n){let E=Number(n[1]);if(E<0||a.toLowerCase().includes("e-")){let y=Math.abs(E),h=Math.pow(10,-y),g=Number(h.toFixed(y));return Math.abs(g-h)<r?g:h}return .1}let s=12,i=t.toFixed(s).replace(/0+$/,""),u=Math.min((i.split(".")[1]||"").length,s);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 re(e,r=1e-8){let t=e.paramType==="Integer";if(G(e,{transform:Te()}),t){Array.isArray(e.default)?e.default=e.default.map(s=>typeof s=="number"?Math.round(s):s):typeof e.default=="number"&&(e.default=Math.round(e.default)),e.stepSize=1;return}let a=Array.isArray(e.default)?e.default[0]:e.default,n;if(typeof a=="number"&&Number.isFinite(a)&&a!==0?n=a:typeof e.minimum=="number"&&Number.isFinite(e.minimum)&&e.minimum!==0?n=e.minimum:typeof e.maximum=="number"&&Number.isFinite(e.maximum)&&e.maximum!==0&&(n=e.maximum),n!==void 0?e.stepSize=xe(n,r):e.stepSize=.1,typeof e.stepSize=="number"){let s=0,o=String(e.stepSize),i=o.toLowerCase().match(/e(-?\d+)/);if(i?s=Math.abs(Number(i[1])):s=o.split(".")[1]?.length??0,s===0&&typeof a=="number"&&a!==0&&Math.abs(a)<1){let u=Math.ceil(-Math.log10(Math.abs(a)));Number.isFinite(u)&&u>0&&(s=u)}s=Math.min(Math.max(s,0),12),Array.isArray(e.default)?e.default=e.default.map(u=>typeof u=="number"?ee(u,s,r):u):typeof e.default=="number"&&(e.default=ee(e.default,s,r))}}function Pe(e){try{G(e,{transform:be(),setUndefinedOnEmpty:!1})}catch(r){throw r instanceof Error?new l(r.message):r}}function Ce(e){G(e,{transform:De(),setUndefinedOnEmpty:!1})}function te(e){G(e,{transform:Ie(e.nickname||"unnamed"),setUndefinedOnEmpty:!0})}function Se(e){if(!e.values||typeof e.values!="object"||Object.keys(e.values).length===0)throw l.missingValues(e.nickname||"unnamed","ValueList");if(e.default!==void 0&&e.default!==null){let r=String(e.default).toLowerCase();Object.keys(e.values).some(a=>a.toLowerCase()===r)||f().warn(`ValueList input "${e.nickname||"unnamed"}" default value "${e.default}" is not in available values`)}}var ae={Number:re,Integer:re,Boolean:Pe,Text:Ce,ValueList:Se,Geometry:te,File:te};L();function Re(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 R(e){let r={description:e.description,name:e.name,nickname:e.nickname,treeAccess:e.treeAccess,groupName:e.groupName??"",id:e.id};try{Q(e);let t=ae[e.paramType];if(!t)throw l.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 l.unknownParamType(e.paramType,e.name)}}catch(t){if(t instanceof l)return f().error(`Validation error for input ${e.name||"unknown"}:`,t.message),Re(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 x(e){return e.map(r=>R(r))}async function b(e,r){let t=M(e,[]),a={};t.algo&&(a.algo=t.algo),t.pointer&&(a.pointer=t.pointer);let n=await O("io",a,r);if(!n||typeof n!="object")throw new l("Invalid IO response structure",c.INVALID_INPUT,{context:{response:n,definition:e}});let s=A(n,{deep:!0});return{inputs:s.inputs,outputs:s.outputs}}async function C(e,r){w("fetchParsedDefinitionIO",r.suppressClientSideWarning);let{inputs:t,outputs:a}=await b(e,r);return{inputs:x(t),outputs:a}}var v=class e{constructor(r){d(this,"innerTree");d(this,"paramName");this.paramName=r,this.innerTree={}}append(r,t){let a=e.formatPathString(r);this.innerTree[a]||(this.innerTree[a]=[]);let n=t.map(s=>({data:e.serializeValue(s)}));return this.innerTree[a].push(...n),this}appendSingle(r,t){return this.append(r,[t])}fromDataTreeDefault(r){this.innerTree={};for(let[t,a]of Object.entries(r)){if(!Array.isArray(a))continue;let n=e.parsePathString(t);this.append(n,a)}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 a of t)r.push(e.deserializeValue(a.data));return r}getPaths(){return Object.keys(this.innerTree)}getPath(r){let t=e.formatPathString(r),a=this.innerTree[t];if(a)return a.map(n=>e.deserializeValue(n.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 a=new e(t.nickname||"unnamed"),n=t.default;if(t.treeAccess&&e.isDataTreeStructure(n))a.fromDataTreeDefault(n),e.isNumericInput(t)&&a.applyNumericConstraints(t.minimum,t.maximum,t.nickname||"unnamed");else{let s=Array.isArray(n)?n:[n],o=e.processValues(s,t);a.appendFlat(o)}return a.toComputeFormat()})}static fromInputParam(r){return e.hasValidValue(r.default)?e.fromInputParams([r])[0]:void 0}static replaceTreeValue(r,t,a){if(r.length>0&&r[0]instanceof e){let s=r,o=s.findIndex(u=>u.getParamName()===t),i=new e(t);return typeof a=="object"&&a!==null&&!Array.isArray(a)&&e.isDataTreeStructure(a)?i.fromDataTreeDefault(a):(Array.isArray(a),i.appendFlat(a)),o!==-1?s[o]=i:s.push(i),s}else{let s=r,o=s.findIndex(p=>p.ParamName===t),i=new e(t);typeof a=="object"&&a!==null&&!Array.isArray(a)&&e.isDataTreeStructure(a)?i.fromDataTreeDefault(a):(Array.isArray(a),i.appendFlat(a));let u=i.toComputeFormat();return o!==-1?s[o]=u:s.push(u),s}}static getTreeValue(r,t){if(r.length>0&&r[0]instanceof e){let s=r.find(i=>i.getParamName()===t);if(!s)return null;let o=s.flatten();return o.length===0?null:o.length===1?o[0]:o}else{let s=r.find(p=>p.ParamName===t);if(!s)return null;let o=s.InnerTree;if(!o)return null;let i=Object.keys(o)[0];if(!i)return null;let u=o[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):(f().warn(`Invalid TreeBuilder path format: ${r}, using [0]`),[0])}static formatPathString(r){return`{${r.join(";")}}`}applyNumericConstraints(r,t,a){for(let n of Object.values(this.innerTree))if(Array.isArray(n))for(let s of n){let o=e.deserializeValue(s.data);if(typeof o=="number"){let i=e.clampValue(o,r,t,a);s.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,a])=>typeof t=="string"&&/^\{[\d;]+\}$/.test(t)&&Array.isArray(a))}static isNumericInput(r){return r.paramType==="Number"||r.paramType==="Integer"}static processValues(r,t){return r.map(a=>e.isNumericInput(t)&&typeof a=="number"?e.clampValue(a,t.minimum,t.maximum,t.nickname||"unnamed"):a).filter(a=>a!=null)}static clampValue(r,t,a,n){let s=r;return t!=null&&s<t&&(f().warn(`${n}: ${r} below min ${t}, clamping`),s=t),a!=null&&s>a&&(f().warn(`${n}: ${r} above max ${a}, clamping`),s=a),s}};export{T as a,B as b,S as c,I as d,P as e,R as f,x as g,b as h,C as i,v as j};
|
|
2
|
+
//# sourceMappingURL=chunk-FMFP7GIM.js.map
|