@selvajs/compute 4.2.2-beta.0 → 5.0.0-beta.10
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 +125 -99
- package/dist/core.d.ts +190 -2
- package/dist/core.js +1 -1
- package/dist/grasshopper.d.ts +317 -772
- package/dist/grasshopper.js +3081 -1
- package/dist/grasshopper.js.map +1 -1
- package/dist/handle-files-D-4X4Uh_.js +1379 -0
- package/dist/handle-files-D-4X4Uh_.js.map +1 -0
- package/dist/types-Dm9QFVvA.d.ts +247 -0
- package/package.json +21 -83
- package/dist/core-BSKhoCtA.js +0 -3
- package/dist/core-BSKhoCtA.js.map +0 -1
- package/dist/core-C9chLkyW.cjs +0 -3
- package/dist/core-C9chLkyW.cjs.map +0 -1
- package/dist/core.cjs +0 -1
- package/dist/core.d.cts +0 -2
- package/dist/grasshopper.cjs +0 -2
- package/dist/grasshopper.cjs.map +0 -1
- package/dist/grasshopper.d.cts +0 -1790
- package/dist/index-zlzEAi12.d.cts +0 -572
- package/dist/index-zlzEAi12.d.ts +0 -572
- package/dist/index.cjs +0 -0
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
package/dist/grasshopper.d.ts
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { c as ComputeAuth, f as ServerTiming, l as ComputeConfig, n as FileBaseInfo, o as SolveDefinition, p as ComputeError, u as RetryPolicy } from "./types-Dm9QFVvA.js";
|
|
2
|
+
interface ServerVersion {
|
|
3
|
+
rhino: string;
|
|
4
|
+
compute: string;
|
|
5
|
+
git_sha: string | null;
|
|
6
|
+
}
|
|
7
|
+
/** What `GET /limits` reports. Only the VektorNode fork answers it. */
|
|
8
|
+
interface ServerLimits {
|
|
9
|
+
/** Longest the server lets one request run (`RHINO_COMPUTE_TIMEOUT`, `--timeout`). */
|
|
10
|
+
timeoutSeconds: number;
|
|
11
|
+
/** Largest request body it accepts (`RHINO_COMPUTE_MAX_REQUEST_SIZE`, `--max-request-size`). */
|
|
12
|
+
maxRequestBytes: number;
|
|
13
|
+
/** A stale definition pointer answers `definition_not_cached`, so pointer reuse is safe. */
|
|
14
|
+
signalsStaleDefinition: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface ServerStats {
|
|
17
|
+
isOnline: boolean;
|
|
18
|
+
version?: ServerVersion;
|
|
19
|
+
activeChildren?: number;
|
|
20
|
+
}
|
|
3
21
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* @public Use this for server health monitoring and statistics.
|
|
22
|
+
* Server health and control: liveness, version, child processes, cache purges.
|
|
7
23
|
*
|
|
8
24
|
* @example
|
|
9
25
|
* ```typescript
|
|
@@ -23,30 +39,33 @@ import { M as ComputeError, O as ComputeConfig, _ as isDefinitionRef, a as extra
|
|
|
23
39
|
*/
|
|
24
40
|
declare class ComputeServerStats {
|
|
25
41
|
private readonly serverUrl;
|
|
26
|
-
private readonly
|
|
42
|
+
private readonly headers;
|
|
27
43
|
private disposed;
|
|
28
44
|
private activeMonitors;
|
|
29
|
-
private activeTimeouts;
|
|
30
45
|
/** Timeout (ms) for the fast read/monitoring endpoints. */
|
|
31
46
|
private static readonly DEFAULT_TIMEOUT_MS;
|
|
32
47
|
/** Timeout (ms) for child-lifecycle POSTs — a cold Windows child can take ~30s to spawn. */
|
|
33
48
|
private static readonly LIFECYCLE_TIMEOUT_MS;
|
|
34
49
|
/** Floor for `monitor()`'s `intervalMs` — anything lower hot-loops the server. */
|
|
35
50
|
private static readonly MIN_MONITOR_INTERVAL_MS;
|
|
51
|
+
/** Every control-plane answer is a count, a version or a short map. */
|
|
52
|
+
private static readonly MAX_BODY_BYTES;
|
|
36
53
|
/**
|
|
37
54
|
* @param serverUrl - Base URL of the Rhino Compute server with http:// or https:// scheme (e.g., 'http://localhost:6500')
|
|
38
|
-
* @param
|
|
55
|
+
* @param auth - An API key, or the same auth fields a solve's `ComputeConfig` carries
|
|
56
|
+
* (`apiKey`, `apiKeyHeader`, `authToken`, `headers`).
|
|
39
57
|
*/
|
|
40
|
-
constructor(serverUrl: string,
|
|
58
|
+
constructor(serverUrl: string, auth?: string | ComputeAuth);
|
|
41
59
|
/**
|
|
42
|
-
*
|
|
60
|
+
* Aborts after `timeoutMs` so a hung connection can't stall a probe or `monitor()`; `0` disables
|
|
61
|
+
* it. Redirects are not followed: fetch would carry the API key header to the target.
|
|
43
62
|
*/
|
|
44
|
-
private
|
|
63
|
+
private fetchWithTimeout;
|
|
45
64
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
65
|
+
* The response body of `path`, or `null` (logged) on a non-2xx or a network
|
|
66
|
+
* failure. Throws only when disposed.
|
|
48
67
|
*/
|
|
49
|
-
private
|
|
68
|
+
private getText;
|
|
50
69
|
/**
|
|
51
70
|
* Check if the server is online.
|
|
52
71
|
*
|
|
@@ -71,10 +90,11 @@ declare class ComputeServerStats {
|
|
|
71
90
|
*
|
|
72
91
|
* @param timeoutMs - Abort the probe after this many ms (default: 5000).
|
|
73
92
|
* Pass `0` to disable the timeout.
|
|
93
|
+
* @param signal - Cancels the probe, which then reports the abort as its `error`.
|
|
74
94
|
* @returns `online` plus either the HTTP `status` the server answered with,
|
|
75
95
|
* or the `error` the connection attempt failed with.
|
|
76
96
|
*/
|
|
77
|
-
probeServer(timeoutMs?: number): Promise<{
|
|
97
|
+
probeServer(timeoutMs?: number, signal?: AbortSignal): Promise<{
|
|
78
98
|
online: boolean;
|
|
79
99
|
status?: number;
|
|
80
100
|
error?: string;
|
|
@@ -95,16 +115,18 @@ declare class ComputeServerStats {
|
|
|
95
115
|
getActiveChildren(options?: {
|
|
96
116
|
initialize?: boolean;
|
|
97
117
|
}): Promise<number | null>;
|
|
118
|
+
/**
|
|
119
|
+
* The server's request limits, or `null` when it can't report them: a standard rhino.compute
|
|
120
|
+
* has no `/limits`, and neither does an older fork. A missing route is expected, so it isn't
|
|
121
|
+
* logged as a failure.
|
|
122
|
+
*/
|
|
123
|
+
getLimits(): Promise<ServerLimits | null>;
|
|
98
124
|
/**
|
|
99
125
|
* Get the server version information.
|
|
100
126
|
*
|
|
101
127
|
* @returns Version object with rhino, compute, and git_sha, or null if unavailable
|
|
102
128
|
*/
|
|
103
|
-
getVersion(): Promise<
|
|
104
|
-
rhino: string;
|
|
105
|
-
compute: string;
|
|
106
|
-
git_sha: string | null;
|
|
107
|
-
} | null>;
|
|
129
|
+
getVersion(): Promise<ServerVersion | null>;
|
|
108
130
|
/**
|
|
109
131
|
* Get the plugins installed on the server.
|
|
110
132
|
*
|
|
@@ -131,15 +153,7 @@ declare class ComputeServerStats {
|
|
|
131
153
|
*
|
|
132
154
|
* @returns Object containing server status and available stats
|
|
133
155
|
*/
|
|
134
|
-
getServerStats(): Promise<
|
|
135
|
-
isOnline: boolean;
|
|
136
|
-
version?: {
|
|
137
|
-
rhino: string;
|
|
138
|
-
compute: string;
|
|
139
|
-
git_sha: string | null;
|
|
140
|
-
};
|
|
141
|
-
activeChildren?: number;
|
|
142
|
-
}>;
|
|
156
|
+
getServerStats(): Promise<ServerStats>;
|
|
143
157
|
/**
|
|
144
158
|
* Purge the server's solve-results / URL-data cache.
|
|
145
159
|
*
|
|
@@ -284,12 +298,7 @@ declare class ComputeServerStats {
|
|
|
284
298
|
spawned: number[];
|
|
285
299
|
active: number;
|
|
286
300
|
} | null>;
|
|
287
|
-
/**
|
|
288
|
-
* POST a control endpoint that replies with a JSON object and return it,
|
|
289
|
-
* degrading to `null` on any non-2xx, non-JSON, or network failure. Shared by
|
|
290
|
-
* the child-lifecycle methods so their failure semantics stay identical. Uses
|
|
291
|
-
* the longer lifecycle timeout since a spawn/recycle can take ~30s.
|
|
292
|
-
*/
|
|
301
|
+
/** A child-lifecycle POST: a spawn or recycle can take ~30 s. */
|
|
293
302
|
private postJson;
|
|
294
303
|
/**
|
|
295
304
|
* Continuously monitor server stats at specified interval.
|
|
@@ -310,41 +319,29 @@ declare class ComputeServerStats {
|
|
|
310
319
|
* stopMonitoring();
|
|
311
320
|
* ```
|
|
312
321
|
*/
|
|
313
|
-
monitor(callback: (stats:
|
|
322
|
+
monitor(callback: (stats: ServerStats) => void, intervalMs?: number): () => void;
|
|
314
323
|
/**
|
|
315
324
|
* Disposes of all resources and stops all active monitors.
|
|
316
325
|
* Call this when you're done using the stats instance.
|
|
317
326
|
*/
|
|
318
327
|
dispose(): Promise<void>;
|
|
319
|
-
/**
|
|
320
|
-
* Ensures the instance hasn't been disposed.
|
|
321
|
-
*/
|
|
322
328
|
private ensureNotDisposed;
|
|
323
329
|
}
|
|
324
|
-
//#endregion
|
|
325
|
-
//#region src/grasshopper/types/inputs.d.ts
|
|
326
330
|
type DataTreePath = `{${string}}`;
|
|
327
331
|
interface DataItem {
|
|
328
332
|
type: string;
|
|
329
333
|
data: string;
|
|
330
|
-
|
|
334
|
+
/** **Requires:** the VektorNode compute fork. A stock server sends none. */
|
|
335
|
+
id?: string;
|
|
331
336
|
}
|
|
332
337
|
type DataTreeDefault<T = any> = { [K in DataTreePath]?: T[]; };
|
|
333
338
|
type InnerTreeData = { [path in DataTreePath]: DataItem[]; };
|
|
334
339
|
/**
|
|
335
340
|
* Tree with parameter metadata (used in compute requests and responses).
|
|
336
341
|
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
* camelCase-serializing forks return `paramName`/`innerTree` instead. This
|
|
341
|
-
* client always *sends* PascalCase (see `DataTree.toCompute()` in
|
|
342
|
-
* `data-tree.ts`), so the PascalCase fields remain the canonical/required
|
|
343
|
-
* shape; the optional camelCase fields exist so responses from camelCase
|
|
344
|
-
* forks are representable without casts. Code that must read trees across
|
|
345
|
-
* both server families should use `readField`/`hasField`
|
|
346
|
-
* (`@/core/utils/read-field`, case-insensitive) rather than direct property
|
|
347
|
-
* access — `warnOnEmptyInnerTrees` in `solve.ts` is the reference example.
|
|
342
|
+
* This client sends PascalCase (`TreeBuilder.toComputeFormat()`), so those
|
|
343
|
+
* fields are required; a response's casing varies by server branch, so read
|
|
344
|
+
* one with `readField` rather than by property.
|
|
348
345
|
*/
|
|
349
346
|
interface DataTree {
|
|
350
347
|
/** PascalCase — stock mcneel servers, and the request shape this client sends. */
|
|
@@ -356,7 +353,6 @@ interface DataTree {
|
|
|
356
353
|
/** camelCase — sent instead of `ParamName` by camelCase server forks. */
|
|
357
354
|
paramName?: string;
|
|
358
355
|
}
|
|
359
|
-
type OutputType = 'System.String' | 'System.Double' | 'System.Int32' | 'System.Boolean' | 'Rhino.Geometry.Point3d' | 'Rhino.Geometry.Line' | 'Rhino.Geometry.Circle' | 'Rhino.Geometry.Arc' | 'Rhino.Geometry.NurbsCurve' | 'Rhino.Geometry.Brep' | 'Rhino.Geometry.Mesh' | 'Rhino.Geometry.Vector3d' | 'Rhino.Geometry.Plane' | 'Rhino.Geometry.Box' | (string & {});
|
|
360
356
|
/**
|
|
361
357
|
* Union type for all possible default value types
|
|
362
358
|
*/
|
|
@@ -372,12 +368,14 @@ interface BaseInputType {
|
|
|
372
368
|
treeAccess: boolean;
|
|
373
369
|
/**
|
|
374
370
|
* Name of the group this parameter belongs to.
|
|
375
|
-
*
|
|
371
|
+
*
|
|
372
|
+
* **Requires:** the VektorNode compute fork.
|
|
376
373
|
*/
|
|
377
374
|
groupName?: string;
|
|
378
375
|
/**
|
|
379
376
|
* Unique identifier for the parameter.
|
|
380
|
-
*
|
|
377
|
+
*
|
|
378
|
+
* **Requires:** the VektorNode compute fork.
|
|
381
379
|
*/
|
|
382
380
|
id?: string;
|
|
383
381
|
}
|
|
@@ -431,7 +429,7 @@ interface FileInputType extends BaseInputType {
|
|
|
431
429
|
default: DefaultValue<object | string>;
|
|
432
430
|
}
|
|
433
431
|
/**
|
|
434
|
-
* Color input type (
|
|
432
|
+
* Color input type. Values are `"R, G, B"` strings (`"255, 0, 0"`), not hex.
|
|
435
433
|
*/
|
|
436
434
|
interface ColorInputType extends BaseInputType {
|
|
437
435
|
paramType: 'Color';
|
|
@@ -441,8 +439,6 @@ interface ColorInputType extends BaseInputType {
|
|
|
441
439
|
* Discriminated union of all input parameter types
|
|
442
440
|
*/
|
|
443
441
|
type InputParam = NumericInputType | BooleanInputType | TextInputType | ValueListInputType | GeometryInputType | FileInputType | ColorInputType;
|
|
444
|
-
//#endregion
|
|
445
|
-
//#region src/grasshopper/types/schema.d.ts
|
|
446
442
|
type RhinoModelUnit = 'None' | 'Microns' | 'Millimeters' | 'Centimeters' | 'Decimeters' | 'Meters' | 'Kilometers' | 'Mils' | 'Inches' | 'Feet' | 'Yards' | 'Miles' | 'CustomUnits' | 'Unset';
|
|
447
443
|
/**
|
|
448
444
|
* Base Grasshopper schema properties shared by config, args, and response
|
|
@@ -458,15 +454,6 @@ interface GrasshopperBaseSchema {
|
|
|
458
454
|
dataversion?: 7 | 8 | null;
|
|
459
455
|
/** Whether to use cached solution */
|
|
460
456
|
cachesolve?: boolean | null;
|
|
461
|
-
/**
|
|
462
|
-
* Opt-in: cache a solve even when the definition reported GH errors. Default
|
|
463
|
-
* (false/unset) means errored solves are never cached server-side. Some
|
|
464
|
-
* definitions throw GH errors by design (a guarded Python component, a
|
|
465
|
-
* filtered branch) while still producing correct geometry — set this so those
|
|
466
|
-
* still benefit from the server's solve cache. Only meaningful with
|
|
467
|
-
* `cachesolve`. Requires a server that honors it (VektorNode fork).
|
|
468
|
-
*/
|
|
469
|
-
cacheerroredsolves?: boolean | null;
|
|
470
457
|
}
|
|
471
458
|
/**
|
|
472
459
|
* Where a Selva-family plugin running inside the solve may POST live events, and
|
|
@@ -490,55 +477,19 @@ interface GrasshopperDefinitionSource {
|
|
|
490
477
|
filename?: string | null;
|
|
491
478
|
}
|
|
492
479
|
/**
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
* Note: The definition source (pointer/algo) is NOT part of config.
|
|
497
|
-
* Instead, pass the definition directly to methods like solve(), getIO(), etc.
|
|
480
|
+
* Server config plus the Grasshopper solve settings. The definition is not part
|
|
481
|
+
* of it: pass that to `solve()` and friends.
|
|
498
482
|
*/
|
|
499
|
-
interface GrasshopperComputeConfig extends ComputeConfig {
|
|
500
|
-
/** Absolute tolerance used in computation */
|
|
501
|
-
absolutetolerance?: number | null;
|
|
502
|
-
/** Angular tolerance used in computation */
|
|
503
|
-
angletolerance?: number | null;
|
|
504
|
-
/** Model units used */
|
|
505
|
-
modelunits?: RhinoModelUnit | null;
|
|
506
|
-
/** Data version (7 or 8) */
|
|
507
|
-
dataversion?: 7 | 8 | null;
|
|
508
|
-
/** Whether to use cached solution */
|
|
509
|
-
cachesolve?: boolean | null;
|
|
510
|
-
/**
|
|
511
|
-
* Opt-in: cache a solve even when the definition reported GH errors. See
|
|
512
|
-
* {@link GrasshopperBaseSchema.cacheerroredsolves}. Only meaningful with
|
|
513
|
-
* `cachesolve`.
|
|
514
|
-
*/
|
|
515
|
-
cacheerroredsolves?: boolean | null;
|
|
516
|
-
/** Per-solve live-event callback; see {@link SelvaEventTarget}. */
|
|
517
|
-
selvaevents?: SelvaEventTarget | null;
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* Arguments sent to Grasshopper compute endpoint
|
|
521
|
-
* Includes config options + definition source + input values
|
|
522
|
-
*/
|
|
523
|
-
interface GrasshopperRequestSchema extends GrasshopperBaseSchema, GrasshopperDefinitionSource {
|
|
524
|
-
/** Input values organized by parameter */
|
|
525
|
-
values?: DataTree[];
|
|
483
|
+
interface GrasshopperComputeConfig extends ComputeConfig, GrasshopperBaseSchema {
|
|
526
484
|
/** Per-solve live-event callback; see {@link SelvaEventTarget}. */
|
|
527
485
|
selvaevents?: SelvaEventTarget | null;
|
|
528
486
|
}
|
|
529
487
|
/**
|
|
530
|
-
* Response from Grasshopper compute server
|
|
531
|
-
* Includes all schema fields + computed results
|
|
532
|
-
*
|
|
533
|
-
* `pointer` is deliberately excluded (`Omit`): the solve layer (`runSolve` in
|
|
534
|
-
* `solve.ts`) splits the server's echoed `pointer` off as the solve's
|
|
535
|
-
* `cacheKey` and strips it from the returned response, so client-returned
|
|
536
|
-
* responses never carry it.
|
|
488
|
+
* Response from Grasshopper compute server.
|
|
537
489
|
*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
* rely on them without a fallback.
|
|
490
|
+
* No `pointer`: the solve returns the server's echoed pointer as its `cacheKey`
|
|
491
|
+
* instead. The echoed settings (`cachesolve`, `dataversion`) stay optional:
|
|
492
|
+
* nothing client-side enforces them.
|
|
542
493
|
*/
|
|
543
494
|
interface GrasshopperComputeResponse extends GrasshopperBaseSchema, Omit<GrasshopperDefinitionSource, 'pointer'> {
|
|
544
495
|
/**
|
|
@@ -548,12 +499,7 @@ interface GrasshopperComputeResponse extends GrasshopperBaseSchema, Omit<Grassho
|
|
|
548
499
|
* hand-built mock may omit it at runtime.
|
|
549
500
|
*/
|
|
550
501
|
modelunits: RhinoModelUnit;
|
|
551
|
-
/**
|
|
552
|
-
* The server echoes the request's full base64 definition back as `algo`, but the client strips
|
|
553
|
-
* it before returning — retaining it would pin a multi-MB copy of the definition per response,
|
|
554
|
-
* multiplied by every cache that holds responses. Always `undefined` on client-returned
|
|
555
|
-
* responses (inherited optional field from {@link GrasshopperDefinitionSource}).
|
|
556
|
-
*/
|
|
502
|
+
/** Always `undefined` on a client-returned response: the solve strips it. */
|
|
557
503
|
algo?: string | null;
|
|
558
504
|
/** Filename of the definition (always present in response) */
|
|
559
505
|
filename: string | null;
|
|
@@ -618,22 +564,19 @@ interface InputParamSchema {
|
|
|
618
564
|
acceptedFormats?: string[];
|
|
619
565
|
groupName?: string | null;
|
|
620
566
|
}
|
|
621
|
-
|
|
622
|
-
//#region src/grasshopper/types/outputs.d.ts
|
|
623
|
-
/**
|
|
624
|
-
* Parsed input/output structure with raw schemas.
|
|
625
|
-
*
|
|
626
|
-
* `loadWarnings` / `loadErrors` carry the server's definition-load diagnostics
|
|
627
|
-
* (missing plugin, broken component, etc.) from the `/io` response. They are
|
|
628
|
-
* distinct from per-input parse failures (`InputParseError`): these come from
|
|
629
|
-
* the server loading the definition, those from the client typing an input.
|
|
630
|
-
*/
|
|
567
|
+
/** Input/output schemas as the `/io` endpoint reports them, keys canonicalized. */
|
|
631
568
|
interface GrasshopperParsedIORaw {
|
|
632
569
|
inputs: InputParamSchema[];
|
|
633
570
|
outputs: OutputParamSchema[];
|
|
634
|
-
/**
|
|
571
|
+
/**
|
|
572
|
+
* Warnings the server raised loading the definition (e.g. an obsolete
|
|
573
|
+
* component). Distinct from `parseErrors`, the client failing to type an input.
|
|
574
|
+
*/
|
|
635
575
|
loadWarnings?: string[];
|
|
636
|
-
/**
|
|
576
|
+
/**
|
|
577
|
+
* Errors the server raised loading the definition (e.g. a missing plugin).
|
|
578
|
+
* When present, `inputs`/`outputs` may be incomplete.
|
|
579
|
+
*/
|
|
637
580
|
loadErrors?: string[];
|
|
638
581
|
}
|
|
639
582
|
/**
|
|
@@ -652,43 +595,24 @@ interface InputParseError {
|
|
|
652
595
|
/** Error code from the underlying ComputeError, if available. */
|
|
653
596
|
code?: string;
|
|
654
597
|
}
|
|
655
|
-
/**
|
|
656
|
-
|
|
657
|
-
*
|
|
658
|
-
* `parseErrors` is populated when one or more inputs failed validation and
|
|
659
|
-
* fell back to a safe default. The result is still usable, but the UI should
|
|
660
|
-
* surface these so the user can fix their definition.
|
|
661
|
-
*/
|
|
662
|
-
interface GrasshopperParsedIO {
|
|
598
|
+
/** {@link GrasshopperParsedIORaw} with each input parsed into its typed {@link InputParam}. */
|
|
599
|
+
interface GrasshopperParsedIO extends Omit<GrasshopperParsedIORaw, 'inputs'> {
|
|
663
600
|
inputs: InputParam[];
|
|
664
|
-
outputs: OutputParamSchema[];
|
|
665
|
-
parseErrors?: InputParseError[];
|
|
666
601
|
/**
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
* list. Distinct from `parseErrors` (client-side input typing failures).
|
|
602
|
+
* Inputs that failed validation and got a safe default. The result is still
|
|
603
|
+
* usable, but surface these so the user can fix their definition.
|
|
670
604
|
*/
|
|
671
|
-
|
|
672
|
-
/**
|
|
673
|
-
* Server-side definition-load errors from the `/io` response (e.g. a missing
|
|
674
|
-
* plugin that left inputs unresolved). When present, the inputs/outputs may
|
|
675
|
-
* be incomplete — the user needs to fix their server/definition.
|
|
676
|
-
*/
|
|
677
|
-
loadErrors?: string[];
|
|
605
|
+
parseErrors?: InputParseError[];
|
|
678
606
|
}
|
|
679
|
-
//#endregion
|
|
680
|
-
//#region src/grasshopper/scheduler/types.d.ts
|
|
681
607
|
/**
|
|
682
|
-
*
|
|
608
|
+
* How concurrent `solve()` calls interact.
|
|
683
609
|
*
|
|
684
|
-
* - `latest-wins`:
|
|
685
|
-
*
|
|
686
|
-
* - `queue`: FIFO
|
|
687
|
-
*
|
|
688
|
-
* - `parallel`: No scheduling — calls run concurrently up to `maxConcurrent`.
|
|
689
|
-
* Closest to plain `client.solve()` but with shared cancel/state.
|
|
610
|
+
* - `latest-wins`: one in flight at a time. A new call supersedes the pending
|
|
611
|
+
* one and aborts the one in flight. For slider scrubs and live UIs.
|
|
612
|
+
* - `queue`: FIFO, every call runs to completion, up to `maxConcurrent` at
|
|
613
|
+
* once (default 1). For "submit job" flows where every request matters.
|
|
690
614
|
*/
|
|
691
|
-
type SchedulerMode = 'latest-wins' | 'queue'
|
|
615
|
+
type SchedulerMode = 'latest-wins' | 'queue';
|
|
692
616
|
interface CacheOptions {
|
|
693
617
|
/**
|
|
694
618
|
* Total byte budget for retained responses, evicted LRU. The only size bound
|
|
@@ -699,6 +623,8 @@ interface CacheOptions {
|
|
|
699
623
|
* fetch boundary — no re-serialization); a response without that hint
|
|
700
624
|
* (custom executor) is sized by a one-off `JSON.stringify`. A single
|
|
701
625
|
* response larger than the whole budget is served but never retained.
|
|
626
|
+
* Parsed, a response of many small items holds more heap than its wire size,
|
|
627
|
+
* so leave headroom.
|
|
702
628
|
*
|
|
703
629
|
* Required and must be > 0 — to disable caching, pass `cache: false`.
|
|
704
630
|
*/
|
|
@@ -718,12 +644,19 @@ interface CacheOptions {
|
|
|
718
644
|
* Cache responses that carry Grasshopper `errors`. Default `true`: an
|
|
719
645
|
* errored solve is a valid, deterministic result — definitions raise GH
|
|
720
646
|
* errors by design (guarded components, validation branches), so replaying
|
|
721
|
-
* one from cache is correct. Set `false`
|
|
722
|
-
* `cacheerroredsolves` server flag, e.g. when a definition's errors are
|
|
647
|
+
* one from cache is correct. Set `false` when a definition's errors are
|
|
723
648
|
* transient (external data sources) rather than functions of the inputs.
|
|
724
649
|
*/
|
|
725
650
|
cacheErroredSolves?: boolean;
|
|
726
651
|
}
|
|
652
|
+
/** What {@link SolveScheduler.cacheStats} reports. */
|
|
653
|
+
interface CacheStats {
|
|
654
|
+
entries: number;
|
|
655
|
+
bytes: number;
|
|
656
|
+
hits: number;
|
|
657
|
+
misses: number;
|
|
658
|
+
evictions: number;
|
|
659
|
+
}
|
|
727
660
|
interface SolveSchedulerOptions {
|
|
728
661
|
mode?: SchedulerMode;
|
|
729
662
|
maxConcurrent?: number;
|
|
@@ -732,7 +665,7 @@ interface SolveSchedulerOptions {
|
|
|
732
665
|
* excluding the ones already in flight). When the queue is full, a new
|
|
733
666
|
* `solve()` is rejected immediately with `code: QUEUE_FULL` (retryable, meant to
|
|
734
667
|
* map to HTTP 503 + Retry-After) instead of piling up unbounded. Bounds the
|
|
735
|
-
* miss path under load. Only applies to `queue`
|
|
668
|
+
* miss path under load. Only applies to `queue` mode —
|
|
736
669
|
* `latest-wins` has an intrinsic depth of 1. Default: unbounded.
|
|
737
670
|
*/
|
|
738
671
|
maxQueueDepth?: number;
|
|
@@ -740,8 +673,7 @@ interface SolveSchedulerOptions {
|
|
|
740
673
|
* Backpressure — max time (ms) a call may sit queued before it starts
|
|
741
674
|
* executing. If it's still waiting after this long it's rejected with
|
|
742
675
|
* `code: QUEUE_TIMEOUT` rather than burning compute on a stale request.
|
|
743
|
-
* Bounds tail latency. Only applies to `queue`
|
|
744
|
-
* no deadline.
|
|
676
|
+
* Bounds tail latency. Only applies to `queue` mode. Default: no deadline.
|
|
745
677
|
*/
|
|
746
678
|
queueWaitMs?: number;
|
|
747
679
|
timeoutMs?: number;
|
|
@@ -753,15 +685,11 @@ interface SolveSchedulerOptions {
|
|
|
753
685
|
*/
|
|
754
686
|
cache?: false | CacheOptions;
|
|
755
687
|
/**
|
|
756
|
-
*
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
*
|
|
760
|
-
*
|
|
761
|
-
* Requires a `cacheKeyExecutor` to be supplied (the client wires one). Has no
|
|
762
|
-
* effect for URL-pointer definitions (already a reference). On a server-side
|
|
763
|
-
* cache miss the executor transparently falls back to a full upload, so this
|
|
764
|
-
* is safe to leave on. Default: `true` when a `cacheKeyExecutor` is present.
|
|
688
|
+
* Upload a definition once, then solve it by the server's cache key (`pointer`)
|
|
689
|
+
* instead of re-sending the bytes; a `DefinitionRef` also skips its `load()`.
|
|
690
|
+
* When the server has evicted the key, the solve falls back to a full upload,
|
|
691
|
+
* so this is safe to leave on. No effect for URL definitions, which are
|
|
692
|
+
* already a reference. Default `true`.
|
|
765
693
|
*/
|
|
766
694
|
reuseServerDefinitionCache?: boolean;
|
|
767
695
|
/** Lifecycle hooks — fired in order. Errors thrown by hooks are logged, not rethrown. */
|
|
@@ -783,54 +711,54 @@ type SolveResult = {
|
|
|
783
711
|
durationMs: number;
|
|
784
712
|
fromCache: boolean;
|
|
785
713
|
/**
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
*
|
|
789
|
-
*
|
|
790
|
-
* fast path didn't run (reuse disabled, or a non-reusable definition such
|
|
791
|
-
* as a remote URL).
|
|
714
|
+
* Whether this solve uploaded the full definition: `true` on its first
|
|
715
|
+
* solve or after the server evicted the cache key, `false` when the server
|
|
716
|
+
* reused its cached copy via the pointer. `undefined` for a `fromCache`
|
|
717
|
+
* hit, or when reuse is off or the definition is a URL.
|
|
792
718
|
*/
|
|
793
719
|
definitionReuploaded?: boolean;
|
|
794
720
|
} | {
|
|
795
721
|
status: 'error';
|
|
796
722
|
error: ComputeError;
|
|
797
723
|
durationMs: number;
|
|
798
|
-
} | {
|
|
799
|
-
status: 'superseded';
|
|
800
724
|
};
|
|
801
|
-
type SolveExecutor = (definition: SolveDefinition, dataTree: DataTree[], config: GrasshopperComputeConfig) => Promise<GrasshopperComputeResponse>;
|
|
802
725
|
/**
|
|
803
|
-
*
|
|
804
|
-
*
|
|
805
|
-
*
|
|
806
|
-
* scheduler can update its definition→key map, plus whether the fast path
|
|
807
|
-
* `missed` (for telemetry). When `cacheKey` is null it's a first solve — upload
|
|
808
|
-
* fully and capture the key the server assigns.
|
|
809
|
-
*
|
|
810
|
-
* Supplied by the client (which owns the solve primitives); the scheduler stays
|
|
811
|
-
* decoupled from the transport.
|
|
726
|
+
* Solves by `cacheKey` when given one, otherwise uploads. Reports the server's
|
|
727
|
+
* (possibly new) key and whether the full definition was uploaded (`missed`).
|
|
728
|
+
* The scheduler passes `null` whenever server-definition reuse is off.
|
|
812
729
|
*/
|
|
813
|
-
type
|
|
730
|
+
type SolveExecutor = (definition: SolveDefinition, dataTree: DataTree[], cacheKey: string | null, config: GrasshopperComputeConfig) => Promise<{
|
|
814
731
|
response: GrasshopperComputeResponse;
|
|
815
732
|
cacheKey: string | null;
|
|
816
733
|
missed: boolean;
|
|
817
734
|
}>;
|
|
818
|
-
|
|
819
|
-
|
|
735
|
+
interface SchedulerSolveOptions {
|
|
736
|
+
signal?: AbortSignal;
|
|
737
|
+
/** Per-solve live-event callback. Not part of the cache key: it names where events go, not what is solved. */
|
|
738
|
+
selvaevents?: SelvaEventTarget;
|
|
739
|
+
/**
|
|
740
|
+
* This call's `Server-Timing` breakdown, after the client config's own `onServerTiming`.
|
|
741
|
+
* Never fires for a `fromCache` hit, which sends no request.
|
|
742
|
+
*/
|
|
743
|
+
onServerTiming?: (timing: ServerTiming, requestId: string) => void;
|
|
744
|
+
}
|
|
745
|
+
/** What `solveDetailed()` resolves with: the response plus how this call got it. */
|
|
746
|
+
interface SolveDetail {
|
|
747
|
+
response: GrasshopperComputeResponse;
|
|
748
|
+
/** Served from the scheduler's response cache without a request. */
|
|
749
|
+
fromCache: boolean;
|
|
750
|
+
/** Same meaning as on {@link SolveResult}. */
|
|
751
|
+
definitionReuploaded?: boolean;
|
|
752
|
+
/** Executor wall time; `0` for a `fromCache` hit. */
|
|
753
|
+
durationMs: number;
|
|
754
|
+
}
|
|
820
755
|
/**
|
|
821
|
-
*
|
|
822
|
-
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
* - Configurable scheduling (latest-wins for sliders, queue for jobs)
|
|
826
|
-
* - Backpressure (bounded queue depth + queue-wait deadline) for the miss path
|
|
827
|
-
* - In-flight cancellation (per-call signal + cancelAll)
|
|
756
|
+
* Adds to a plain solve call:
|
|
757
|
+
* - Scheduling (latest-wins for sliders, queue for jobs)
|
|
758
|
+
* - Backpressure (bounded queue depth + queue-wait deadline)
|
|
759
|
+
* - Cancellation (per-call signal + cancelAll)
|
|
828
760
|
* - Optional response caching for repeated inputs
|
|
829
|
-
* - Lifecycle hooks
|
|
830
|
-
* - State observability via subscribe()
|
|
831
|
-
*
|
|
832
|
-
* Multiple schedulers can share a single GrasshopperClient — typically one
|
|
833
|
-
* per UI surface (e.g. one for slider scrubs, one for long-running submits).
|
|
761
|
+
* - Lifecycle hooks (start / settle / superseded) and state via subscribe()
|
|
834
762
|
*
|
|
835
763
|
* @example
|
|
836
764
|
* ```ts
|
|
@@ -853,53 +781,32 @@ export declare class SolveScheduler {
|
|
|
853
781
|
private readonly executor;
|
|
854
782
|
private readonly baseConfig;
|
|
855
783
|
private readonly mode;
|
|
856
|
-
/**
|
|
857
|
-
* Mutable via {@link setMaxConcurrent}: the compute server's worker pool can grow
|
|
858
|
-
* or shrink while this scheduler is alive, and the dispatch loops re-read this on
|
|
859
|
-
* every pass rather than capturing it.
|
|
860
|
-
*/
|
|
861
784
|
private maxConcurrent;
|
|
862
785
|
private readonly maxQueueDepth;
|
|
863
786
|
private readonly queueWaitMs;
|
|
864
787
|
private readonly timeoutMs;
|
|
865
788
|
private readonly retry;
|
|
866
|
-
private readonly cacheEnabled;
|
|
867
|
-
private readonly cacheMaxBytes;
|
|
868
|
-
private readonly cacheTtl;
|
|
869
|
-
private readonly cacheErroredSolves;
|
|
870
789
|
private readonly cache;
|
|
871
|
-
/** Sum of `sizeBytes` across retained cache entries. */
|
|
872
|
-
private cacheBytes;
|
|
873
|
-
/**
|
|
874
|
-
* Cumulative hit/miss/eviction counters for {@link cacheStats}. Deliberately
|
|
875
|
-
* NOT reset by `clearCache()` — they measure this scheduler's whole lifetime,
|
|
876
|
-
* so a hit rate stays comparable across a session rather than restarting at
|
|
877
|
-
* every clear.
|
|
878
|
-
*/
|
|
879
|
-
private cacheHits;
|
|
880
|
-
private cacheMisses;
|
|
881
|
-
private cacheEvictions;
|
|
882
|
-
/** Optional cache-key-aware executor and whether server-def-cache reuse is on. */
|
|
883
|
-
private readonly cacheKeyExecutor?;
|
|
884
790
|
private readonly reuseServerDefinitionCache;
|
|
885
|
-
/**
|
|
791
|
+
/** Definition hash → the server's cache key (`pointer`) for it. */
|
|
886
792
|
private readonly serverCacheKeys;
|
|
793
|
+
/** A string definition re-sent unchanged is compared with this, far cheaper than hashing it. */
|
|
794
|
+
private lastStringDefinition;
|
|
887
795
|
private readonly onStart?;
|
|
888
796
|
private readonly onSettle?;
|
|
889
797
|
private readonly onSuperseded?;
|
|
890
798
|
private readonly subscribers;
|
|
891
799
|
private readonly inFlight;
|
|
892
800
|
private pendingForLatestWins;
|
|
893
|
-
private readonly
|
|
801
|
+
private readonly fifo;
|
|
894
802
|
private _lastResult;
|
|
895
803
|
private _lastError;
|
|
896
804
|
private _lastDurationMs;
|
|
897
|
-
/** Ordinal handed to each solve() call. */
|
|
898
805
|
private solveSeq;
|
|
899
|
-
/** seq of the solve that last wrote _lastResult
|
|
806
|
+
/** seq of the solve that last wrote `_lastResult`/`_lastError`. */
|
|
900
807
|
private lastStateSeq;
|
|
901
808
|
private disposed;
|
|
902
|
-
constructor(executor: SolveExecutor, baseConfig: GrasshopperComputeConfig, options?: SolveSchedulerOptions
|
|
809
|
+
constructor(executor: SolveExecutor, baseConfig: GrasshopperComputeConfig, options?: SolveSchedulerOptions);
|
|
903
810
|
get isSolving(): boolean;
|
|
904
811
|
get hasPending(): boolean;
|
|
905
812
|
get inFlightCount(): number;
|
|
@@ -914,10 +821,10 @@ export declare class SolveScheduler {
|
|
|
914
821
|
* Raising it drains queued work immediately. Lowering it never interrupts work
|
|
915
822
|
* already in flight — those finish above the new limit, and the cap applies from
|
|
916
823
|
* the next dispatch. Values below 1 are clamped, since 0 would wedge the queue.
|
|
824
|
+
*
|
|
825
|
+
* @throws {ComputeError} `INVALID_CONFIG` for `NaN`, which would wedge it too.
|
|
917
826
|
*/
|
|
918
827
|
setMaxConcurrent(value: number): void;
|
|
919
|
-
/** Current concurrency cap — reflects any {@link setMaxConcurrent} adjustment. */
|
|
920
|
-
getMaxConcurrent(): number;
|
|
921
828
|
/** Subscribe to state changes. */
|
|
922
829
|
subscribe(listener: () => void): () => void;
|
|
923
830
|
private notify;
|
|
@@ -928,23 +835,16 @@ export declare class SolveScheduler {
|
|
|
928
835
|
* - Rejects with `code: ErrorCodes.SUPERSEDED` when the call was canceled because
|
|
929
836
|
* newer values arrived (latest-wins mode).
|
|
930
837
|
* - Rejects with `code: ErrorCodes.ABORTED` when the call was canceled via
|
|
931
|
-
*
|
|
838
|
+
* its own `signal` (queued or running) or `cancelAll()`.
|
|
932
839
|
* - Rejects with `code: ErrorCodes.QUEUE_FULL` when `maxQueueDepth` is set and
|
|
933
840
|
* the queue was already full (backpressure; `statusCode: 503`).
|
|
934
841
|
* - Rejects with `code: ErrorCodes.QUEUE_TIMEOUT` when `queueWaitMs` is set and
|
|
935
842
|
* the call sat queued longer than that before starting (`statusCode: 503`).
|
|
936
843
|
*
|
|
937
|
-
*
|
|
938
|
-
*
|
|
939
|
-
*
|
|
940
|
-
*
|
|
941
|
-
* server-pointer map alike) without materializing bytes — `load()` runs only
|
|
942
|
-
* when an upload is unavoidable. Its immutability contract is trusted here:
|
|
943
|
-
* a reused key serves the other content's cached solve.
|
|
944
|
-
*
|
|
945
|
-
* Responses served from the cache (and via `lastResult`) are shared objects,
|
|
946
|
-
* not copies — treat them as immutable. Mutating one poisons every later
|
|
947
|
-
* cache hit for that key.
|
|
844
|
+
* Don't mutate a `Uint8Array` definition after solving it. Responses served
|
|
845
|
+
* from the cache (and via `lastResult`) are shared objects, not copies —
|
|
846
|
+
* treat them as immutable. Mutating one poisons every later cache hit for
|
|
847
|
+
* that key.
|
|
948
848
|
*
|
|
949
849
|
* Partial-success contract: unlike `GrasshopperClient.solve()`, which throws
|
|
950
850
|
* `COMPUTATION_ERROR` when the response carries solver errors, this RESOLVES
|
|
@@ -952,80 +852,43 @@ export declare class SolveScheduler {
|
|
|
952
852
|
* success must not be treated as a result (see `cacheErroredSolves` for the
|
|
953
853
|
* caching side of the same distinction).
|
|
954
854
|
*/
|
|
955
|
-
solve(definition: SolveDefinition, dataTree: DataTree[], options?:
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
/**
|
|
960
|
-
* Record last-result state, but only if no newer solve has written since —
|
|
961
|
-
* a slow solve settling late must not overwrite the state a newer solve
|
|
962
|
-
* (or cache hit) already published.
|
|
963
|
-
*/
|
|
855
|
+
solve(definition: SolveDefinition, dataTree: DataTree[], options?: SchedulerSolveOptions): Promise<GrasshopperComputeResponse>;
|
|
856
|
+
/** {@link solve}, also resolving with whether this call hit the cache and how long it took. */
|
|
857
|
+
solveDetailed(definition: SolveDefinition, dataTree: DataTree[], options?: SchedulerSolveOptions): Promise<SolveDetail>;
|
|
858
|
+
/** A slow solve settling late must not overwrite state a newer solve or cache hit published. */
|
|
964
859
|
private writeLastState;
|
|
965
860
|
/** latest-wins: supersede the pending item and abort everything in flight. */
|
|
966
861
|
private supersedeCurrent;
|
|
967
|
-
|
|
862
|
+
private dequeue;
|
|
968
863
|
private abortQueuedItem;
|
|
969
|
-
/**
|
|
970
|
-
* Backpressure: settle an incoming item as QUEUE_FULL without ever enqueuing
|
|
971
|
-
* it. The structured context lets an HTTP layer map it to 503 + Retry-After.
|
|
972
|
-
*/
|
|
864
|
+
/** The structured context lets an HTTP layer map QUEUE_FULL to 503 + Retry-After. */
|
|
973
865
|
private shedAsQueueFull;
|
|
974
|
-
/**
|
|
975
|
-
* Arm the queue-wait deadline for an item about to be queued. If the item is
|
|
976
|
-
* still waiting when it fires, it's rejected as QUEUE_TIMEOUT and removed from
|
|
977
|
-
* the queue. Cleared on execute/settle via {@link clearQueueWaitTimer}.
|
|
978
|
-
*/
|
|
979
866
|
private armQueueWaitTimer;
|
|
980
|
-
/** Clear a queued item's wait-deadline timer, if one is pending. */
|
|
981
867
|
private clearQueueWaitTimer;
|
|
982
868
|
private enqueue;
|
|
983
869
|
private execute;
|
|
984
|
-
/**
|
|
985
|
-
* Run the solve, using the server-definition-cache fast path when it's
|
|
986
|
-
* enabled and the definition is reusable. Learns/updates the definition's
|
|
987
|
-
* server cache key from the result so later solves can reference it.
|
|
988
|
-
*
|
|
989
|
-
* `definitionHash` is the {@link hashDefinition} result already computed at
|
|
990
|
-
* `solve()` entry — threaded through rather than recomputed, so each solve
|
|
991
|
-
* pays exactly one linear pass over the definition (issue 57).
|
|
992
|
-
*/
|
|
993
870
|
private runExecutor;
|
|
871
|
+
private hashDefinitionMemo;
|
|
994
872
|
private drainNext;
|
|
995
873
|
private supersede;
|
|
996
874
|
private makeAbortError;
|
|
997
875
|
/**
|
|
998
|
-
*
|
|
999
|
-
*
|
|
1000
|
-
*
|
|
1001
|
-
*
|
|
1002
|
-
* promise silently ignores a second settle. This guard is the single place the
|
|
1003
|
-
* settle-once invariant lives: it makes the *first* settle win and reports
|
|
1004
|
-
* whether this call was that winner, so callers fire their own hook only when
|
|
1005
|
-
* they actually settled. Any new settle path must go through here (or
|
|
1006
|
-
* {@link settleSuccess}) so the guard can't be forgotten.
|
|
1007
|
-
*
|
|
1008
|
-
* @returns `true` if this call settled the item; `false` if it was already settled.
|
|
876
|
+
* The executor, `supersede`, `cancelAll`, abort and the queue limits can all race to settle one
|
|
877
|
+
* item, and a promise ignores a second settle silently. The first settle wins; the return value
|
|
878
|
+
* says whether this call won, so only the winner fires its hook. Every settle path goes through
|
|
879
|
+
* here or {@link settleSuccess}.
|
|
1009
880
|
*/
|
|
1010
881
|
private settleError;
|
|
1011
882
|
/**
|
|
1012
|
-
*
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1015
|
-
* @returns `true` if this call settled the item; `false` if it was already settled.
|
|
883
|
+
* Fires `onSettle` for queued items too, so a consumer counting solves in progress doesn't
|
|
884
|
+
* leak one. A supersede settles through {@link settleError} and fires `onSuperseded` instead.
|
|
1016
885
|
*/
|
|
886
|
+
private fail;
|
|
1017
887
|
private settleSuccess;
|
|
1018
|
-
|
|
1019
|
-
private removeQueuedAbortHandler;
|
|
1020
|
-
private isAbortLikeError;
|
|
888
|
+
private claimSettle;
|
|
1021
889
|
private normalizeExecutionError;
|
|
1022
890
|
/** Cancel everything — in-flight and pending. */
|
|
1023
891
|
cancelAll(): void;
|
|
1024
|
-
private rejectAsAborted;
|
|
1025
|
-
private readCache;
|
|
1026
|
-
private writeCache;
|
|
1027
|
-
/** Remove one cache entry and release its bytes from the running total. */
|
|
1028
|
-
private dropCacheEntry;
|
|
1029
892
|
clearCache(): void;
|
|
1030
893
|
/**
|
|
1031
894
|
* Observability snapshot of the solve cache: current size plus lifetime
|
|
@@ -1037,18 +900,10 @@ export declare class SolveScheduler {
|
|
|
1037
900
|
* replace-in-place writes or TTL expiry, which are not capacity signals.
|
|
1038
901
|
* Counters are cumulative and survive `clearCache()`.
|
|
1039
902
|
*/
|
|
1040
|
-
cacheStats():
|
|
1041
|
-
entries: number;
|
|
1042
|
-
bytes: number;
|
|
1043
|
-
hits: number;
|
|
1044
|
-
misses: number;
|
|
1045
|
-
evictions: number;
|
|
1046
|
-
};
|
|
903
|
+
cacheStats(): CacheStats;
|
|
1047
904
|
dispose(): void;
|
|
1048
905
|
private runHook;
|
|
1049
906
|
}
|
|
1050
|
-
//#endregion
|
|
1051
|
-
//#region src/grasshopper/client/grasshopper-client.d.ts
|
|
1052
907
|
/**
|
|
1053
908
|
* Per-call options that override the client's default ComputeConfig values.
|
|
1054
909
|
*
|
|
@@ -1064,14 +919,24 @@ interface SolveOptions {
|
|
|
1064
919
|
/** Per-solve live-event callback, forwarded onto the request body. */
|
|
1065
920
|
selvaevents?: SelvaEventTarget;
|
|
1066
921
|
}
|
|
922
|
+
/** Options for {@link GrasshopperClient.create} that shape construction, not the solves. */
|
|
923
|
+
interface CreateClientOptions {
|
|
924
|
+
/**
|
|
925
|
+
* Retry ladder for the liveness probe: `attempts` retries after the first probe (default 2),
|
|
926
|
+
* with exponential backoff from `baseDelayMs` (default 250) capped at `maxDelayMs` (default 1000).
|
|
927
|
+
* Independent of `config.retry`, which governs solves only.
|
|
928
|
+
*/
|
|
929
|
+
probe?: {
|
|
930
|
+
attempts?: number;
|
|
931
|
+
baseDelayMs?: number;
|
|
932
|
+
maxDelayMs?: number;
|
|
933
|
+
};
|
|
934
|
+
}
|
|
1067
935
|
/**
|
|
1068
|
-
*
|
|
936
|
+
* The high-level API for solving Grasshopper definitions on a Rhino Compute server.
|
|
1069
937
|
*
|
|
1070
|
-
*
|
|
1071
|
-
*
|
|
1072
|
-
* **Security Warning:**
|
|
1073
|
-
* Using this client in a browser environment exposes your server URL and API key to users.
|
|
1074
|
-
* For production, use this library server-side or proxy requests through your own backend.
|
|
938
|
+
* In a browser, the server URL and API key are exposed to users: run it server-side, or proxy
|
|
939
|
+
* requests through your own backend.
|
|
1075
940
|
*
|
|
1076
941
|
* @example
|
|
1077
942
|
* ```typescript
|
|
@@ -1081,7 +946,8 @@ interface SolveOptions {
|
|
|
1081
946
|
* });
|
|
1082
947
|
*
|
|
1083
948
|
* try {
|
|
1084
|
-
* const
|
|
949
|
+
* const io = await client.getIO(definitionUrl);
|
|
950
|
+
* const result = await client.solve(definitionUrl, TreeBuilder.fromInputParams(io.inputs));
|
|
1085
951
|
* } finally {
|
|
1086
952
|
* await client.dispose(); // Clean up resources
|
|
1087
953
|
* }
|
|
@@ -1090,43 +956,26 @@ interface SolveOptions {
|
|
|
1090
956
|
declare class GrasshopperClient {
|
|
1091
957
|
private readonly config;
|
|
1092
958
|
readonly serverStats: ComputeServerStats;
|
|
959
|
+
private readonly schedulers;
|
|
1093
960
|
private disposed;
|
|
1094
961
|
/**
|
|
1095
|
-
* Per-probe timeout for the `create()` liveness gate
|
|
1096
|
-
*
|
|
1097
|
-
* is not answering, where every extra second is multiplied by the retry count
|
|
1098
|
-
* and paid by whoever is waiting on the solve.
|
|
962
|
+
* Per-probe timeout for the `create()` liveness gate: a healthy `GET /` answers in milliseconds,
|
|
963
|
+
* so this only bounds a silent server, and every extra second is paid once per retry.
|
|
1099
964
|
*/
|
|
1100
965
|
private static readonly CREATE_PROBE_TIMEOUT_MS;
|
|
1101
966
|
private constructor();
|
|
1102
967
|
/**
|
|
1103
|
-
* Creates
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
1106
|
-
*
|
|
1107
|
-
* as offline. To avoid failing construction on that transient class, the probe
|
|
1108
|
-
* is retried with a short exponential backoff before giving up.
|
|
968
|
+
* Creates a client once a liveness probe (`GET /`) says the server is up. A cold server can read
|
|
969
|
+
* as offline, so the probe retries with a short backoff, stopping early when
|
|
970
|
+
* {@link classifyProbeFailure} says waiting can't change the answer. `config.signal` cancels the
|
|
971
|
+
* ladder.
|
|
1109
972
|
*
|
|
1110
|
-
*
|
|
1111
|
-
*
|
|
1112
|
-
*
|
|
1113
|
-
*
|
|
1114
|
-
*
|
|
1115
|
-
* Each probe is bounded by {@link CREATE_PROBE_TIMEOUT_MS} rather than the
|
|
1116
|
-
* stats default: a healthy `GET /` answers in milliseconds, so a longer
|
|
1117
|
-
* per-probe timeout only multiplies the wait when the server is unreachable.
|
|
1118
|
-
*
|
|
1119
|
-
* @throws {ComputeError} with code NETWORK_ERROR if the server stays
|
|
1120
|
-
* unreachable across all attempts. `context.probeVerdict` carries the
|
|
1121
|
-
* {@link ProbeVerdict} so callers can render a specific cause.
|
|
1122
|
-
* @throws {ComputeError} with code INVALID_CONFIG if configuration is invalid
|
|
1123
|
-
*/
|
|
1124
|
-
static create(config: GrasshopperComputeConfig): Promise<GrasshopperClient>;
|
|
1125
|
-
/**
|
|
1126
|
-
* Gets the client's configuration.
|
|
1127
|
-
* Useful for passing to lower-level functions.
|
|
973
|
+
* @throws {ComputeError} `NETWORK_ERROR` if the server stays unreachable across all attempts.
|
|
974
|
+
* `context.probeVerdict` carries the verdict, so a caller can render a specific cause.
|
|
975
|
+
* @throws {ComputeError} `ABORTED` if `config.signal` fires first.
|
|
976
|
+
* @throws {ComputeError} `INVALID_CONFIG` if the configuration is invalid.
|
|
1128
977
|
*/
|
|
1129
|
-
|
|
978
|
+
static create(config: GrasshopperComputeConfig, options?: CreateClientOptions): Promise<GrasshopperClient>;
|
|
1130
979
|
/**
|
|
1131
980
|
* Get input/output parameters of a Grasshopper definition.
|
|
1132
981
|
*/
|
|
@@ -1156,34 +1005,31 @@ declare class GrasshopperClient {
|
|
|
1156
1005
|
* @example
|
|
1157
1006
|
* ```ts
|
|
1158
1007
|
* const sliderScheduler = client.createScheduler({ mode: 'latest-wins' });
|
|
1159
|
-
* const submitScheduler = client.createScheduler({ mode: 'queue', timeoutMs: 0
|
|
1008
|
+
* const submitScheduler = client.createScheduler({ mode: 'queue', timeoutMs: 0 });
|
|
1160
1009
|
* ```
|
|
1161
1010
|
*/
|
|
1162
1011
|
createScheduler(options?: SolveSchedulerOptions): SolveScheduler;
|
|
1163
|
-
/**
|
|
1164
|
-
* Disposes of client resources.
|
|
1165
|
-
* Call this when you're done using the client.
|
|
1166
|
-
*/
|
|
1012
|
+
/** Disposes of client resources, including every scheduler it created. */
|
|
1167
1013
|
dispose(): Promise<void>;
|
|
1168
|
-
/**
|
|
1169
|
-
* Ensures the client hasn't been disposed.
|
|
1170
|
-
*/
|
|
1171
1014
|
private ensureNotDisposed;
|
|
1172
|
-
/**
|
|
1173
|
-
* Validates and normalizes a compute configuration.
|
|
1174
|
-
*
|
|
1175
|
-
* @throws {ComputeError} with code INVALID_CONFIG if configuration is invalid
|
|
1176
|
-
*/
|
|
1177
|
-
private normalizeComputeConfig;
|
|
1178
1015
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1016
|
+
/**
|
|
1017
|
+
* The part of rhino3dm the decoders call. Structural so the public types don't name `rhino3dm`, a
|
|
1018
|
+
* dev dependency here. A loaded `RhinoModule` satisfies it.
|
|
1019
|
+
*/
|
|
1020
|
+
interface RhinoRuntime {
|
|
1021
|
+
Point: new (location: number[]) => unknown;
|
|
1022
|
+
Line: new (from: number[], to: number[]) => unknown;
|
|
1023
|
+
CommonObject: {
|
|
1024
|
+
decode(jsonObject: object): unknown;
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1181
1027
|
interface ParsedContext {
|
|
1182
1028
|
[key: string]: any;
|
|
1183
1029
|
}
|
|
1184
1030
|
interface GetValuesOptions {
|
|
1185
1031
|
parseValues?: boolean;
|
|
1186
|
-
rhino?:
|
|
1032
|
+
rhino?: RhinoRuntime;
|
|
1187
1033
|
/**
|
|
1188
1034
|
* If true, only include values of type System.String in the result.
|
|
1189
1035
|
* Non-string types are filtered out.
|
|
@@ -1201,41 +1047,13 @@ interface GetValuesResult<T = ParsedContext> {
|
|
|
1201
1047
|
*/
|
|
1202
1048
|
dispose: () => void;
|
|
1203
1049
|
}
|
|
1204
|
-
|
|
1205
|
-
//#region src/grasshopper/client/grasshopper-response-processor.d.ts
|
|
1206
|
-
/**
|
|
1207
|
-
* High-level wrapper for interacting with Grasshopper Compute responses.
|
|
1208
|
-
*
|
|
1209
|
-
* This class exposes a clean, consistent API for accessing parsed values,
|
|
1210
|
-
* geometry, and produced files. It is designed to be the primary interface
|
|
1211
|
-
* when working with Grasshopper results in client applications.
|
|
1212
|
-
*/
|
|
1050
|
+
/** Reads parsed values and produced files out of one compute response. */
|
|
1213
1051
|
declare class GrasshopperResponseProcessor {
|
|
1214
|
-
/**
|
|
1215
|
-
* The raw compute response. Public so callers can hand it to a renderer-side parser — e.g.
|
|
1216
|
-
* `getThreeMeshesFromComputeResponse` in `@selvajs/visualization/parse`, which replaced this
|
|
1217
|
-
* class's former `extractMeshesFromResponse()`.
|
|
1218
|
-
*/
|
|
1052
|
+
/** Hand it to a mesh parser such as `@selvajs/visualization/parse`. */
|
|
1219
1053
|
readonly response: GrasshopperComputeResponse;
|
|
1220
|
-
/**
|
|
1221
|
-
* Retained for call-signature compatibility. Its only consumer was the removed
|
|
1222
|
-
* `extractMeshesFromResponse()`, which merged it into the parse options; pass `debug`
|
|
1223
|
-
* directly to the parser in `@selvajs/visualization/parse` instead.
|
|
1224
|
-
*/
|
|
1225
|
-
readonly debug: boolean;
|
|
1226
1054
|
constructor(
|
|
1227
|
-
/**
|
|
1228
|
-
|
|
1229
|
-
* `getThreeMeshesFromComputeResponse` in `@selvajs/visualization/parse`, which replaced this
|
|
1230
|
-
* class's former `extractMeshesFromResponse()`.
|
|
1231
|
-
*/
|
|
1232
|
-
response: GrasshopperComputeResponse,
|
|
1233
|
-
/**
|
|
1234
|
-
* Retained for call-signature compatibility. Its only consumer was the removed
|
|
1235
|
-
* `extractMeshesFromResponse()`, which merged it into the parse options; pass `debug`
|
|
1236
|
-
* directly to the parser in `@selvajs/visualization/parse` instead.
|
|
1237
|
-
*/
|
|
1238
|
-
debug?: boolean);
|
|
1055
|
+
/** Hand it to a mesh parser such as `@selvajs/visualization/parse`. */
|
|
1056
|
+
response: GrasshopperComputeResponse);
|
|
1239
1057
|
/**
|
|
1240
1058
|
* Extract all values in the response.
|
|
1241
1059
|
*
|
|
@@ -1272,26 +1090,11 @@ declare class GrasshopperResponseProcessor {
|
|
|
1272
1090
|
} | {
|
|
1273
1091
|
byId: string;
|
|
1274
1092
|
}, options?: GetValuesOptions): any;
|
|
1275
|
-
/**
|
|
1276
|
-
* REMOVED: `extractMeshesFromResponse()`. Mesh decoding lives in `@selvajs/visualization` now, so
|
|
1277
|
-
* this package stays pure solve/data and carries no `three` dependency. Call the parser directly
|
|
1278
|
-
* with the raw response:
|
|
1279
|
-
*
|
|
1280
|
-
* ```ts
|
|
1281
|
-
* import { getThreeMeshesFromComputeResponse } from '@selvajs/visualization/parse';
|
|
1282
|
-
*
|
|
1283
|
-
* const meshes = await getThreeMeshesFromComputeResponse(processor.response, { rhino });
|
|
1284
|
-
* scene.add(...meshes);
|
|
1285
|
-
* ```
|
|
1286
|
-
*/
|
|
1287
|
-
private getFileData;
|
|
1288
1093
|
/**
|
|
1289
1094
|
* Download all files generated by Grasshopper, optionally including
|
|
1290
1095
|
* additional user-provided files.
|
|
1291
1096
|
*
|
|
1292
|
-
*
|
|
1293
|
-
*
|
|
1294
|
-
* @param folderName - Name for the download directory.
|
|
1097
|
+
* @param folderName - Name of the zip archive, without the extension.
|
|
1295
1098
|
* @param additionalFiles - Extra files to package (single file, array, or null).
|
|
1296
1099
|
*
|
|
1297
1100
|
* @example
|
|
@@ -1301,14 +1104,12 @@ declare class GrasshopperResponseProcessor {
|
|
|
1301
1104
|
*
|
|
1302
1105
|
* @example
|
|
1303
1106
|
* ```ts
|
|
1304
|
-
* const extra = {
|
|
1107
|
+
* const extra = { fileName: 'notes.txt', filePath: 'https://example.com/notes.txt' };
|
|
1305
1108
|
* await processor.getAndDownloadFiles('project', extra);
|
|
1306
1109
|
* ```
|
|
1307
1110
|
*/
|
|
1308
1111
|
getAndDownloadFiles(folderName: string, additionalFiles?: FileBaseInfo[] | FileBaseInfo | null): Promise<void>;
|
|
1309
1112
|
}
|
|
1310
|
-
//#endregion
|
|
1311
|
-
//#region src/grasshopper/scheduler/stable-hash.d.ts
|
|
1312
1113
|
/**
|
|
1313
1114
|
* Deterministic stringify with sorted keys. {a:1,b:2} and {b:2,a:1} produce
|
|
1314
1115
|
* the same string. Safely handles circular references and non-finite numbers.
|
|
@@ -1316,102 +1117,51 @@ declare class GrasshopperResponseProcessor {
|
|
|
1316
1117
|
* The output is a cache key, so the invariant that matters is: two payloads
|
|
1317
1118
|
* that serialize differently on the wire must stringify differently here
|
|
1318
1119
|
* (false misses are harmless; false hits serve the wrong cached solve).
|
|
1120
|
+
* Non-JSON values get unquoted markers (`{u8:…}`, `[Circular]`) that no JSON
|
|
1121
|
+
* value stringifies to, so a plain object can't pose as one.
|
|
1319
1122
|
*/
|
|
1320
1123
|
export declare function stableStringify(value: unknown): string;
|
|
1321
|
-
/**
|
|
1322
|
-
* Hash definition and data tree into a stable cache key.
|
|
1323
|
-
*
|
|
1324
|
-
* The definition is the *identity* of what we solve, so a binary definition is
|
|
1325
|
-
* hashed over its full content (`fnv1aBytes`) — a length-only or sampled key
|
|
1326
|
-
* would let two different `.gh` files collide and serve one's cached solve for
|
|
1327
|
-
* the other. `.gh` files are small enough that a single linear pass is
|
|
1328
|
-
* negligible. A {@link DefinitionRef} is keyed by its `key` alone — the
|
|
1329
|
-
* caller-declared identity of immutable bytes — so no bytes are materialized
|
|
1330
|
-
* or hashed at all.
|
|
1331
|
-
*
|
|
1332
|
-
* The key keeps the definition and tree hashes as separate parts rather than
|
|
1333
|
-
* collapsing them into one 32-bit hash: a single FNV pass over the pair would
|
|
1334
|
-
* birthday-collide quadratically in cache size, while requiring both 32-bit
|
|
1335
|
-
* parts (plus lengths) to collide at once makes that negligible.
|
|
1336
|
-
*/
|
|
1124
|
+
/** The scheduler's solve-cache key for a definition and its input tree. */
|
|
1337
1125
|
export declare function hashSolveInput(definition: SolveDefinition, dataTree: unknown): string;
|
|
1338
1126
|
/**
|
|
1339
|
-
*
|
|
1340
|
-
*
|
|
1341
|
-
* with different inputs. Same full-content hashing as {@link hashSolveInput}: a
|
|
1342
|
-
* binary definition is hashed over all its bytes so two distinct `.gh` files of
|
|
1343
|
-
* equal length can't share a cache key. A {@link DefinitionRef} is keyed by its
|
|
1344
|
-
* `key` verbatim (refs are short identities like UUIDs, safe as Map keys) —
|
|
1345
|
-
* its immutability contract makes the key equivalent to a content hash.
|
|
1127
|
+
* A definition's identity, without its inputs. Strings and bytes are hashed over their full
|
|
1128
|
+
* content; a `DefinitionRef` uses its `key`.
|
|
1346
1129
|
*/
|
|
1347
1130
|
export declare function hashDefinition(definition: SolveDefinition): string;
|
|
1348
|
-
//#endregion
|
|
1349
|
-
//#region src/grasshopper/solve.d.ts
|
|
1350
1131
|
/**
|
|
1351
|
-
*
|
|
1352
|
-
*
|
|
1353
|
-
* @public Use this for direct compute control. For high-level API, use `GrasshopperClient.solve()`.
|
|
1132
|
+
* Run one solve. `GrasshopperClient.solve()` adds input validation and throws on solver errors.
|
|
1354
1133
|
*
|
|
1355
|
-
* @param
|
|
1356
|
-
*
|
|
1357
|
-
*
|
|
1358
|
-
* - A base64-encoded string of the .gh file
|
|
1359
|
-
* - A plain string (will be base64-encoded)
|
|
1360
|
-
* - A Uint8Array of the .gh file (will be base64-encoded)
|
|
1361
|
-
* - A `DefinitionRef` (bytes are loaded via `ref.load()` for the upload)
|
|
1362
|
-
* @param config - Compute configuration (server URL, API key, etc. along with optional timeout, units, etc.)
|
|
1363
|
-
* @returns An object containing the compute result and extracted file data.
|
|
1134
|
+
* @param definition - A URL (sent as a pointer), base64 `.gh` content, raw `.gh` bytes, or a
|
|
1135
|
+
* `DefinitionRef` (loaded for the upload). Any other string is encoded as the definition text.
|
|
1136
|
+
* @returns The compute response, without the server's `pointer` and echoed `algo`.
|
|
1364
1137
|
*
|
|
1365
1138
|
* @example
|
|
1366
|
-
* // Using a URL
|
|
1367
1139
|
* await solveGrasshopperDefinition(trees, 'https://example.com/definition.gh', config);
|
|
1368
|
-
*
|
|
1369
|
-
* // Using a base64 string
|
|
1370
|
-
* await solveGrasshopperDefinition(trees, 'UEsDBBQAAAAIAL...', config);
|
|
1371
|
-
*
|
|
1372
|
-
* // Using binary data
|
|
1373
|
-
* const fileData = new Uint8Array([...]);
|
|
1374
|
-
* await solveGrasshopperDefinition(trees, fileData, config);
|
|
1140
|
+
* await solveGrasshopperDefinition(trees, new Uint8Array(await readFile('model.gh')), config);
|
|
1375
1141
|
*/
|
|
1376
1142
|
export declare function solveGrasshopperDefinition(dataTree: DataTree[], definition: SolveDefinition, config: GrasshopperComputeConfig): Promise<GrasshopperComputeResponse>;
|
|
1377
|
-
//#endregion
|
|
1378
|
-
//#region src/grasshopper/io/definition-io.d.ts
|
|
1379
1143
|
/**
|
|
1380
|
-
* Fetches
|
|
1144
|
+
* Fetches a definition's input/output schemas without per-type parsing.
|
|
1381
1145
|
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
* ({@link normalizeInputSchema} / {@link normalizeOutputSchema}, with honest
|
|
1386
|
-
* fallbacks for missing required fields), missing/non-array `inputs`/`outputs`
|
|
1387
|
-
* coerce to `[]`, and server load diagnostics surface as
|
|
1388
|
-
* `loadWarnings`/`loadErrors` (coerced to strings). Field VALUES — notably
|
|
1389
|
-
* `default` and the `values` dropdown-label map — pass through verbatim.
|
|
1146
|
+
* Field KEYS are canonicalized to camelCase and missing required fields get a fallback; a missing
|
|
1147
|
+
* or non-array `inputs` / `outputs` becomes `[]`. Field VALUES, notably `default` and the `values`
|
|
1148
|
+
* label map, pass through verbatim.
|
|
1390
1149
|
*
|
|
1391
|
-
* @param definition - The Grasshopper definition (URL, base64 string, or Uint8Array)
|
|
1392
|
-
* @param config - Compute configuration (server URL, API key, etc.)
|
|
1393
|
-
* @returns Key-normalized inputs and outputs with no per-type processing
|
|
1394
1150
|
* @throws {ComputeError} If fetch fails or response is invalid
|
|
1395
|
-
*
|
|
1396
|
-
* @public Use `fetchParsedDefinitionIO()` for processed, type-safe inputs
|
|
1397
1151
|
*/
|
|
1398
1152
|
export declare function fetchDefinitionIO(definition: string | Uint8Array, config: ComputeConfig): Promise<GrasshopperParsedIORaw>;
|
|
1399
1153
|
/**
|
|
1400
|
-
* Fetches
|
|
1401
|
-
*
|
|
1402
|
-
*
|
|
1403
|
-
* @public This is the recommended way to fetch definition I/O schemas.
|
|
1154
|
+
* Fetches a definition's input/output schemas and parses each input into its
|
|
1155
|
+
* typed `InputParam`. An input that fails to parse gets a safe default
|
|
1156
|
+
* and an entry in `parseErrors`.
|
|
1404
1157
|
*
|
|
1405
|
-
* @param definition - The Grasshopper definition (URL, base64 string, or Uint8Array)
|
|
1406
|
-
* @param config - Compute configuration (server URL, API key, etc.)
|
|
1407
|
-
* @returns Processed inputs with discriminated union types and outputs
|
|
1408
1158
|
* @throws {ComputeError} If fetch fails or response is invalid
|
|
1409
1159
|
*
|
|
1410
1160
|
* @example
|
|
1411
1161
|
* ```typescript
|
|
1412
1162
|
* const { inputs, outputs } = await fetchParsedDefinitionIO(
|
|
1413
1163
|
* 'https://example.com/definition.gh',
|
|
1414
|
-
* { serverUrl: '
|
|
1164
|
+
* { serverUrl: 'http://localhost:6500', apiKey: 'YOUR_KEY' }
|
|
1415
1165
|
* );
|
|
1416
1166
|
*
|
|
1417
1167
|
* // Inputs are now strongly typed
|
|
@@ -1423,8 +1173,6 @@ export declare function fetchDefinitionIO(definition: string | Uint8Array, confi
|
|
|
1423
1173
|
* ```
|
|
1424
1174
|
*/
|
|
1425
1175
|
export declare function fetchParsedDefinitionIO(definition: string | Uint8Array, config: ComputeConfig): Promise<GrasshopperParsedIO>;
|
|
1426
|
-
//#endregion
|
|
1427
|
-
//#region src/grasshopper/io/schema-endpoint.d.ts
|
|
1428
1176
|
/** One entry of the schema endpoint's response, after wrapper-key normalization. */
|
|
1429
1177
|
interface SchemaEndpointResult<TSchema = unknown> {
|
|
1430
1178
|
/** Schemas embedded in that file. Absent when the file yielded none. */
|
|
@@ -1436,101 +1184,79 @@ interface SchemaEndpointResult<TSchema = unknown> {
|
|
|
1436
1184
|
* Read compute's `/grasshopper/schema` body: `[{ FileName, Schemas }]` per
|
|
1437
1185
|
* uploaded file, or a bare object for a single file.
|
|
1438
1186
|
*
|
|
1439
|
-
* Use this rather than unwrapping the body by hand
|
|
1440
|
-
* by server branch
|
|
1441
|
-
*
|
|
1442
|
-
* half the servers, and the endpoint answers 200 either way. The failure looks
|
|
1443
|
-
* like "this definition has no schemas", which sends you debugging the wrong
|
|
1444
|
-
* thing entirely.
|
|
1445
|
-
*
|
|
1446
|
-
* A blanket key-rewrite (the old `camelcaseKeys` approach) is NOT the fix: it
|
|
1447
|
-
* reaches inside the schemas and mangles user-authored names — `"Display3d"` →
|
|
1448
|
-
* `"display3d"`, value-list labels like `"Option A"` → `"optionA"`. Only the two
|
|
1449
|
-
* wrapper keys are read here; schema CONTENTS pass through untouched, which is
|
|
1450
|
-
* why `TSchema` is a pass-through type parameter this module never inspects.
|
|
1187
|
+
* Use this rather than unwrapping the body by hand: the wrapper keys' casing
|
|
1188
|
+
* varies by server branch, and a fixed-key read yields "no schemas" with a 200.
|
|
1189
|
+
* Only the two wrapper keys are read; schema contents pass through untouched.
|
|
1451
1190
|
*
|
|
1452
1191
|
* @typeParam TSchema - Your schema type (e.g. `UISchema`). Not inspected.
|
|
1453
|
-
* @param raw - The parsed JSON body.
|
|
1454
1192
|
*/
|
|
1455
1193
|
export declare function readSchemaResults<TSchema = unknown>(raw: unknown): SchemaEndpointResult<TSchema>[];
|
|
1456
|
-
//#endregion
|
|
1457
|
-
//#region src/grasshopper/io/normalize-ui-schema.d.ts
|
|
1458
1194
|
/**
|
|
1459
|
-
* Canonicalize a `/grasshopper/schema` body's key
|
|
1460
|
-
*
|
|
1461
|
-
* ## Why this exists
|
|
1462
|
-
*
|
|
1463
|
-
* Compute serializes the plugin's `UISchema` POCO, whose camelCase wire names
|
|
1464
|
-
* live in Newtonsoft `[JsonProperty]` attributes. `Selva.gha` ILRepack-merges
|
|
1465
|
-
* Newtonsoft into itself, so those attributes have type
|
|
1466
|
-
* `Selva!Newtonsoft.Json.JsonPropertyAttribute`. When the serializer that runs is
|
|
1467
|
-
* compute's OWN Newtonsoft assembly, it does not recognize that type as its own
|
|
1468
|
-
* attribute, reads no attributes at all, and falls back to raw CLR member names —
|
|
1469
|
-
* emitting `Inputs`/`Layout`/`SchemaVersion`.
|
|
1470
|
-
*
|
|
1471
|
-
* Nothing throws on the wire. Every consumer reads `schema.inputs` as
|
|
1472
|
-
* `undefined`, so the definition renders with no inputs, and `schemaVersion`
|
|
1473
|
-
* reads `undefined` — which also silently disables the newer-plugin version gate.
|
|
1195
|
+
* Canonicalize a `/grasshopper/schema` body's key casing.
|
|
1474
1196
|
*
|
|
1475
|
-
*
|
|
1476
|
-
*
|
|
1197
|
+
* Compute serializes the plugin's `UISchema`, whose camelCase wire names live in
|
|
1198
|
+
* Newtonsoft `[JsonProperty]` attributes. `Selva.gha` ILRepack-merges Newtonsoft,
|
|
1199
|
+
* so those attributes are `Selva!Newtonsoft.Json.JsonPropertyAttribute`. When
|
|
1200
|
+
* compute's OWN Newtonsoft serializes, it doesn't recognize them, reads no
|
|
1201
|
+
* attributes, and emits raw CLR names (`Inputs`, `SchemaVersion`). Nothing throws:
|
|
1202
|
+
* `schema.inputs` reads `undefined`, and so does the `schemaVersion` gate.
|
|
1477
1203
|
*
|
|
1478
|
-
*
|
|
1479
|
-
*
|
|
1480
|
-
*
|
|
1481
|
-
* so reproducing that strategy covers every key. An allowlist would have to
|
|
1482
|
-
* enumerate every structural key in `UISchema` and drift out of date each time
|
|
1483
|
-
* the schema gains a field, failing silently and in exactly this way again.
|
|
1484
|
-
*
|
|
1485
|
-
* ## What it does NOT touch
|
|
1486
|
-
*
|
|
1487
|
-
* `options`, `defaultOptions` and `values` hold USER-AUTHORED keys — dropdown
|
|
1488
|
-
* labels like `"Standart Beschichtung"`, `"Use 10 Elements instead"`, `"True"`.
|
|
1489
|
-
* Those maps are copied verbatim; only the key naming them is canonicalized.
|
|
1490
|
-
* Rewriting their contents is the exact regression that motivated deleting the
|
|
1491
|
-
* old global `camelcaseKeys` pass (see `read-field.ts`), which mangled
|
|
1492
|
-
* `"Option A"` into `"optionA"` and silently changed what a definition solved
|
|
1493
|
-
* with.
|
|
1494
|
-
*
|
|
1495
|
-
* Values are never inspected — only object keys are rewritten.
|
|
1204
|
+
* A casing rule, not a key allowlist: the wire names are the CLR names run
|
|
1205
|
+
* through Newtonsoft's camelCase strategy, so reproducing it covers every key
|
|
1206
|
+
* without drifting each time `UISchema` gains a field.
|
|
1496
1207
|
*/
|
|
1497
1208
|
/**
|
|
1498
|
-
* Returns a schema whose structural keys are camelCase,
|
|
1499
|
-
*
|
|
1500
|
-
*
|
|
1501
|
-
* object the caller may mutate).
|
|
1502
|
-
*
|
|
1503
|
-
* Safe to call on any parsed JSON value; non-objects are returned as-is.
|
|
1209
|
+
* Returns a schema whose structural keys are camelCase, whichever Newtonsoft
|
|
1210
|
+
* serialized it. Always a fresh object the caller may mutate; non-objects are
|
|
1211
|
+
* returned as-is.
|
|
1504
1212
|
*/
|
|
1505
1213
|
export declare function normalizeUISchemaCasing<T>(raw: T): T;
|
|
1506
|
-
//#endregion
|
|
1507
|
-
//#region src/grasshopper/io/input/input-processors.d.ts
|
|
1508
1214
|
/**
|
|
1509
1215
|
* Parse one raw Grasshopper input schema into a typed {@link InputParam}.
|
|
1510
|
-
*
|
|
1511
|
-
* {@link processInputWithError} to receive them.
|
|
1216
|
+
* A validation failure is swallowed and replaced with a safe default.
|
|
1512
1217
|
*/
|
|
1513
1218
|
export declare function processInput(rawInput: InputParamSchema): InputParam;
|
|
1514
|
-
//#endregion
|
|
1515
|
-
//#region src/grasshopper/data-tree/data-tree.d.ts
|
|
1516
1219
|
/**
|
|
1517
|
-
*
|
|
1220
|
+
* Sentinel a Rhino geometry decode returns when a decode was attempted
|
|
1221
|
+
* and failed hard (a registered decoder or `CommonObject.decode` threw). Carries
|
|
1222
|
+
* the original payload so callers can log or retry. Use
|
|
1223
|
+
* {@link isRhinoDecodeError} to detect it.
|
|
1518
1224
|
*/
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
*/
|
|
1524
|
-
|
|
1525
|
-
data: string | boolean | number;
|
|
1225
|
+
interface RhinoDecodeError {
|
|
1226
|
+
__decodeError: true;
|
|
1227
|
+
/** The Rhino type name the failed decode was attempted for. */
|
|
1228
|
+
type: string;
|
|
1229
|
+
/** The original (undecoded) payload. */
|
|
1230
|
+
raw: unknown;
|
|
1526
1231
|
}
|
|
1232
|
+
/** Type guard for the {@link RhinoDecodeError} sentinel. */
|
|
1233
|
+
export declare function isRhinoDecodeError(value: unknown): value is RhinoDecodeError;
|
|
1527
1234
|
/**
|
|
1528
|
-
*
|
|
1235
|
+
* Free every rhino3dm WASM object reachable from `value`.
|
|
1236
|
+
*
|
|
1237
|
+
* rhino3dm objects are emscripten bindings — JS GC never reclaims their WASM
|
|
1238
|
+
* heap allocation, so everything decoded from a solve response (`getValues`,
|
|
1239
|
+
* `getValue`) must be deleted explicitly or the heap
|
|
1240
|
+
* grows monotonically across solves (e.g. a UI decoding per slider tick).
|
|
1241
|
+
*
|
|
1242
|
+
* Walks arrays and plain objects recursively; anything exposing a `delete()`
|
|
1243
|
+
* method is treated as a WASM binding and freed (skipped if already deleted).
|
|
1244
|
+
* Safe to call more than once and on values containing no WASM objects.
|
|
1529
1245
|
*/
|
|
1530
|
-
|
|
1246
|
+
export declare function disposeRhinoObjects(value: unknown): void;
|
|
1247
|
+
type DataTreeValue = string | number | boolean | object | null;
|
|
1248
|
+
/** One input's value for {@link TreeBuilder.fromValues}. */
|
|
1249
|
+
interface TreeValueEntry {
|
|
1250
|
+
paramName: string;
|
|
1251
|
+
/** Matched case-insensitively. */
|
|
1252
|
+
paramType: string;
|
|
1253
|
+
/** A scalar, an array (branch `{0}`), or a branch-path map like `{ '{0;1}': [1, 2] }`. */
|
|
1254
|
+
value: unknown;
|
|
1255
|
+
minimum?: number | null;
|
|
1256
|
+
maximum?: number | null;
|
|
1257
|
+
}
|
|
1531
1258
|
/**
|
|
1532
|
-
*
|
|
1533
|
-
* Does not depend on RhinoCompute library.
|
|
1259
|
+
* Builds the Grasshopper data trees a solve takes as input.
|
|
1534
1260
|
*
|
|
1535
1261
|
* @example
|
|
1536
1262
|
* ```ts
|
|
@@ -1544,247 +1270,66 @@ export declare class TreeBuilder {
|
|
|
1544
1270
|
private innerTree;
|
|
1545
1271
|
private paramName;
|
|
1546
1272
|
constructor(paramName: string);
|
|
1547
|
-
/**
|
|
1548
|
-
* Append values to a specific path in the tree.
|
|
1549
|
-
*
|
|
1550
|
-
* @param path - Array of integers representing the branch path (e.g., [0], [0, 1])
|
|
1551
|
-
* @param items - Values to append at this path
|
|
1552
|
-
* @returns this for method chaining
|
|
1553
|
-
*/
|
|
1273
|
+
/** Append values to the branch at `path` (`[0, 1]` is `{0;1}`). A `null` item is skipped. */
|
|
1554
1274
|
append(path: number[], items: DataTreeValue[]): this;
|
|
1555
|
-
/**
|
|
1556
|
-
* Append a single value to a path.
|
|
1557
|
-
*
|
|
1558
|
-
* @param path - Branch path
|
|
1559
|
-
* @param item - Single value to append
|
|
1560
|
-
* @returns this for method chaining
|
|
1561
|
-
*/
|
|
1562
|
-
appendSingle(path: number[], item: DataTreeValue): this;
|
|
1563
|
-
/**
|
|
1564
|
-
* Set values from a DataTreeDefault structure.
|
|
1565
|
-
* Replaces any existing tree data.
|
|
1566
|
-
*
|
|
1567
|
-
* @param treeData - TreeBuilder structure with path keys like "{0;1}"
|
|
1568
|
-
* @returns this for method chaining
|
|
1569
|
-
*/
|
|
1275
|
+
/** Replace the tree with a branch-path map like `{ '{0;1}': [1, 2] }`. */
|
|
1570
1276
|
fromDataTreeDefault(treeData: DataTreeDefault): this;
|
|
1571
|
-
/**
|
|
1572
|
-
* Append flattened values to path [0].
|
|
1573
|
-
* Useful for simple flat inputs.
|
|
1574
|
-
*
|
|
1575
|
-
* @param values - Single value or array of values
|
|
1576
|
-
* @returns this for method chaining
|
|
1577
|
-
*/
|
|
1277
|
+
/** Append a value, or each value of an array, to branch `{0}`. */
|
|
1578
1278
|
appendFlat(values: DataTreeValue | DataTreeValue[]): this;
|
|
1579
|
-
/**
|
|
1580
|
-
* Get the flattened list of all values in the tree.
|
|
1581
|
-
*
|
|
1582
|
-
* @returns Array of all values across all branches
|
|
1583
|
-
*/
|
|
1584
|
-
flatten(): DataTreeValue[];
|
|
1585
|
-
/**
|
|
1586
|
-
* Get all paths in the tree.
|
|
1587
|
-
*
|
|
1588
|
-
* @returns Array of path strings
|
|
1589
|
-
*/
|
|
1590
|
-
getPaths(): DataTreePath[];
|
|
1591
|
-
/**
|
|
1592
|
-
* Get values at a specific path.
|
|
1593
|
-
*
|
|
1594
|
-
* @param path - Path to retrieve values from
|
|
1595
|
-
* @returns Array of values or undefined if path doesn't exist
|
|
1596
|
-
*/
|
|
1597
|
-
getPath(path: number[]): DataTreeValue[] | undefined;
|
|
1598
|
-
/**
|
|
1599
|
-
* Convert to format compatible with Grasshopper Compute API.
|
|
1600
|
-
*
|
|
1601
|
-
* @returns InnerTree object ready for compute
|
|
1602
|
-
*/
|
|
1279
|
+
/** The tree in the shape a solve request sends. */
|
|
1603
1280
|
toComputeFormat(): DataTree;
|
|
1604
1281
|
/**
|
|
1605
|
-
*
|
|
1606
|
-
*
|
|
1607
|
-
* @returns InnerTree data
|
|
1608
|
-
*/
|
|
1609
|
-
getInnerTree(): ComputeInnerTreeData;
|
|
1610
|
-
/**
|
|
1611
|
-
* Get the parameter name.
|
|
1612
|
-
*
|
|
1613
|
-
* @returns Parameter name
|
|
1614
|
-
*/
|
|
1615
|
-
getParamName(): string;
|
|
1616
|
-
/**
|
|
1617
|
-
* Create DataTrees from an array of InputParam definitions.
|
|
1618
|
-
* Handles tree access, numeric constraints, and value parsing.
|
|
1619
|
-
*
|
|
1620
|
-
* @param inputs - Array of input parameter definitions
|
|
1621
|
-
* @returns Array of InnerTree instances ready for compute
|
|
1622
|
-
*
|
|
1623
|
-
* @example
|
|
1624
|
-
* ```ts
|
|
1625
|
-
* const trees = TreeBuilder.fromInputParams(inputs);
|
|
1626
|
-
* ```
|
|
1282
|
+
* One tree per input that has a default, keyed by its nickname. Defaults are coerced and
|
|
1283
|
+
* clamped by the same rules as {@link TreeBuilder.fromValues}.
|
|
1627
1284
|
*/
|
|
1628
1285
|
static fromInputParams(inputs: InputParam[]): DataTree[];
|
|
1629
1286
|
/**
|
|
1630
|
-
*
|
|
1631
|
-
*
|
|
1632
|
-
*
|
|
1633
|
-
*
|
|
1287
|
+
* One tree per entry, coercing UI values the way Grasshopper reads them. Number and Integer
|
|
1288
|
+
* items go through the numeric coercion (Integer rounds) and are clamped to
|
|
1289
|
+
* `minimum`/`maximum`; Boolean items also accept `'true'`/`'false'`; every other type passes
|
|
1290
|
+
* through. An item that fails coercion is dropped with a warning. An entry left with no items
|
|
1291
|
+
* is omitted, so Grasshopper uses its own value; `''` is an item, not an empty value.
|
|
1634
1292
|
*/
|
|
1635
|
-
static
|
|
1293
|
+
static fromValues(entries: TreeValueEntry[]): DataTree[];
|
|
1294
|
+
private static branchesOf;
|
|
1295
|
+
/** `null` means the item was rejected. */
|
|
1296
|
+
private static itemCoercer;
|
|
1636
1297
|
/**
|
|
1637
|
-
* Set or
|
|
1638
|
-
*
|
|
1639
|
-
*
|
|
1640
|
-
*
|
|
1641
|
-
* **Architecture Note:**
|
|
1642
|
-
* - Use with `DataTree[]` when building/modifying before computation
|
|
1643
|
-
* - Use with `InnerTree[]` when modifying compute API results
|
|
1644
|
-
* - `DataTree` is the high-level builder; `InnerTree` is the Rhino Compute format
|
|
1645
|
-
*
|
|
1646
|
-
* Copy-on-write: returns a new array; the caller's array is never mutated.
|
|
1647
|
-
*
|
|
1648
|
-
* @overload For TreeBuilder instances (high-level builder)
|
|
1649
|
-
* @param trees - Array of TreeBuilder instances to read from (not mutated)
|
|
1650
|
-
* @param paramName - The parameter name to set or replace
|
|
1651
|
-
* @param newValue - The new value (scalar, array, or TreeBuilder structure)
|
|
1652
|
-
* @returns A new TreeBuilder array with the updated parameter
|
|
1653
|
-
*
|
|
1654
|
-
* @overload For compiled InnerTree (low-level API format)
|
|
1655
|
-
* @param trees - The compiled InnerTree array (typically from `client.solve()`; not mutated)
|
|
1656
|
-
* @param paramName - The parameter name to set or replace
|
|
1657
|
-
* @param newValue - The new value (scalar, array, or TreeBuilder structure)
|
|
1658
|
-
* @returns A new InnerTree array with the updated parameter
|
|
1659
|
-
*
|
|
1660
|
-
* @example
|
|
1661
|
-
* ```ts
|
|
1662
|
-
* // With TreeBuilder instances (high-level)
|
|
1663
|
-
* let trees = [new TreeBuilder('X'), new TreeBuilder('Y')];
|
|
1664
|
-
* trees = TreeBuilder.replaceTreeValue(trees, 'X', 42);
|
|
1665
|
-
* const result = await client.solve(definitionUrl,
|
|
1666
|
-
* trees.map(t => t.toComputeFormat())
|
|
1667
|
-
* );
|
|
1668
|
-
* ```
|
|
1669
|
-
*
|
|
1670
|
-
* @example
|
|
1671
|
-
* ```ts
|
|
1672
|
-
* // With InnerTree format (low-level, from API)
|
|
1673
|
-
* let trees = await client.solve(definitionUrl, initialInputs);
|
|
1674
|
-
* trees = TreeBuilder.replaceTreeValue(trees, 'X', 42);
|
|
1675
|
-
* trees = TreeBuilder.replaceTreeValue(trees, 'Y', [1, 2, 3]);
|
|
1676
|
-
* ```
|
|
1298
|
+
* Set or add `paramName`'s tree to `newValue`: a scalar, an array (branch `{0}`), or a
|
|
1299
|
+
* branch-path map. Copy-on-write: returns a new array and leaves the caller's untouched, so
|
|
1300
|
+
* assign the result.
|
|
1677
1301
|
*/
|
|
1678
|
-
static replaceTreeValue(trees: TreeBuilder[], paramName: string, newValue: DataTreeValue): TreeBuilder[];
|
|
1679
1302
|
static replaceTreeValue(trees: DataTree[], paramName: string, newValue: DataTreeValue): DataTree[];
|
|
1303
|
+
private static buildFromValue;
|
|
1680
1304
|
/**
|
|
1681
|
-
*
|
|
1682
|
-
*
|
|
1305
|
+
* `paramName`'s whole tree from a solve result's `values`, keyed by branch path (`'{0;1}'`).
|
|
1306
|
+
* `null` when no tree has that param, an empty `Map` when it has no branches. An item without
|
|
1307
|
+
* `data` reads as `null` in place, so indices don't shift.
|
|
1683
1308
|
*/
|
|
1684
|
-
|
|
1309
|
+
static getTree(trees: DataTree[], paramName: string): Map<DataTreePath, DataTreeValue[]> | null;
|
|
1685
1310
|
/**
|
|
1686
|
-
*
|
|
1687
|
-
*
|
|
1688
|
-
* Automatically unwraps single values for convenience.
|
|
1689
|
-
* Works with both high-level `DataTree[]` instances and low-level `InnerTree[]` format.
|
|
1311
|
+
* `paramName`'s value when its tree has a single branch: one item unwrapped (`5`, not `[5]`),
|
|
1312
|
+
* several as an array. `null` for a missing param or an empty tree.
|
|
1690
1313
|
*
|
|
1691
|
-
*
|
|
1692
|
-
*
|
|
1693
|
-
* - Use with `InnerTree[]` to read compute API responses
|
|
1694
|
-
* - Return behavior is consistent across both formats
|
|
1695
|
-
*
|
|
1696
|
-
* **Return Value Behavior:**
|
|
1697
|
-
* - Single value → unwrapped (returns `5` not `[5]`)
|
|
1698
|
-
* - Multiple values → array of values
|
|
1699
|
-
* - Not found → `null`
|
|
1700
|
-
*
|
|
1701
|
-
* @overload For TreeBuilder instances
|
|
1702
|
-
* @param trees - Array of TreeBuilder instances to read from
|
|
1703
|
-
* @param paramName - The parameter name to retrieve
|
|
1704
|
-
* @returns The unwrapped value, array of values, or null if parameter not found
|
|
1705
|
-
*
|
|
1706
|
-
* @overload For compiled InnerTree
|
|
1707
|
-
* @param trees - The compiled InnerTree array (typically from `client.solve()`)
|
|
1708
|
-
* @param paramName - The parameter name to retrieve
|
|
1709
|
-
* @returns The unwrapped value, array of values, or null if parameter not found
|
|
1710
|
-
*
|
|
1711
|
-
* @example
|
|
1712
|
-
* ```ts
|
|
1713
|
-
* // With TreeBuilder instances
|
|
1714
|
-
* const trees = [new TreeBuilder('X'), new TreeBuilder('Y')];
|
|
1715
|
-
* trees[0].appendFlat(42);
|
|
1716
|
-
* const x = TreeBuilder.getTreeValue(trees, 'X'); // Returns 42
|
|
1717
|
-
* ```
|
|
1718
|
-
*
|
|
1719
|
-
* @example
|
|
1720
|
-
* ```ts
|
|
1721
|
-
* // With InnerTree from compute results
|
|
1722
|
-
* const result = await client.solve(definitionUrl, inputs);
|
|
1723
|
-
* const x = TreeBuilder.getTreeValue(result, 'X'); // Returns 42 (not [42])
|
|
1724
|
-
* const points = TreeBuilder.getTreeValue(result, 'Points'); // Returns [point1, point2, ...]
|
|
1725
|
-
* ```
|
|
1314
|
+
* @throws {ComputeError} `INVALID_INPUT` when the tree has more than one branch; read those
|
|
1315
|
+
* with {@link TreeBuilder.getTree}.
|
|
1726
1316
|
*/
|
|
1727
|
-
static getTreeValue(trees: TreeBuilder[], paramName: string): DataTreeValue | null;
|
|
1728
1317
|
static getTreeValue(trees: DataTree[], paramName: string): DataTreeValue | null;
|
|
1318
|
+
private static paramNameOf;
|
|
1729
1319
|
/**
|
|
1730
|
-
*
|
|
1731
|
-
* Returns null when the builder isn't found.
|
|
1732
|
-
*/
|
|
1733
|
-
private static readFromBuilders;
|
|
1734
|
-
/**
|
|
1735
|
-
* Read values from the first branch of the matching compiled InnerTree
|
|
1736
|
-
* (multi-branch responses are not flattened — current semantics, pinned by
|
|
1737
|
-
* the "reads from the first branch path only" test).
|
|
1738
|
-
*/
|
|
1739
|
-
private static readFromDataTrees;
|
|
1740
|
-
/**
|
|
1741
|
-
* Parse a TreeBuilder path string like "{0;1;2}" into [0, 1, 2].
|
|
1742
|
-
* Negative indices ("{-1;2}") and the root path "{}" are valid.
|
|
1320
|
+
* Parse a branch path like `"{0;1;2}"` into `[0, 1, 2]`.
|
|
1743
1321
|
*
|
|
1744
|
-
* @
|
|
1745
|
-
*
|
|
1746
|
-
* @throws {ComputeError} `INVALID_INPUT` when the path string is not a valid
|
|
1747
|
-
* Grasshopper branch path. Malformed keys must never silently collapse to a
|
|
1748
|
-
* default branch — two distinct unparseable keys would merge their items
|
|
1749
|
-
* into one branch.
|
|
1322
|
+
* @throws {ComputeError} `INVALID_INPUT` for a malformed path, rather than
|
|
1323
|
+
* collapsing it to a default branch where two bad keys would merge.
|
|
1750
1324
|
*/
|
|
1751
1325
|
static parsePathString(pathStr: string): number[];
|
|
1752
|
-
/**
|
|
1753
|
-
* Format a path array into TreeBuilder path string format.
|
|
1754
|
-
*
|
|
1755
|
-
* @param path - Path as number array
|
|
1756
|
-
* @returns Formatted path string like "{0;1;2}"
|
|
1757
|
-
*/
|
|
1326
|
+
/** `[0, 1, 2]` → `"{0;1;2}"`. */
|
|
1758
1327
|
static formatPathString(path: number[]): DataTreePath;
|
|
1759
|
-
/**
|
|
1760
|
-
private applyNumericConstraints;
|
|
1761
|
-
/**
|
|
1762
|
-
* Serialize a value for compute requests.
|
|
1763
|
-
* Preserves booleans and numbers as primitives for proper Grasshopper parameter handling.
|
|
1764
|
-
*/
|
|
1328
|
+
/** Booleans and numbers stay primitives: Grasshopper reads them typed. */
|
|
1765
1329
|
private static serializeValue;
|
|
1766
|
-
/**
|
|
1767
|
-
* Deserialize a value back to its original type.
|
|
1768
|
-
* Handles both string-encoded values and primitive values.
|
|
1769
|
-
*/
|
|
1770
1330
|
private static deserializeValue;
|
|
1771
|
-
/**
|
|
1772
|
-
* Check if a value is valid for inclusion in a DataTree.
|
|
1773
|
-
*/
|
|
1774
1331
|
private static hasValidValue;
|
|
1775
|
-
/**
|
|
1776
|
-
* Check if input is numeric type.
|
|
1777
|
-
*/
|
|
1778
|
-
private static isNumericInput;
|
|
1779
|
-
/**
|
|
1780
|
-
* Process array of values based on input type.
|
|
1781
|
-
*/
|
|
1782
|
-
private static processValues;
|
|
1783
|
-
/**
|
|
1784
|
-
* Clamp numeric value to constraints.
|
|
1785
|
-
*/
|
|
1786
1332
|
private static clampValue;
|
|
1787
1333
|
}
|
|
1788
|
-
|
|
1789
|
-
export { type BooleanInputType, type CacheOptions, ComputeServerStats, type DataItem, type DataTree, type DataTreeDefault, type DataTreePath, type DataTreeValue, type DefaultValue, type DefinitionRef, type FileBaseInfo, type FileData, type FileInputType, type GeometryInputType, type GetValuesOptions, type GetValuesResult, GrasshopperClient, type GrasshopperComputeConfig, type GrasshopperComputeResponse, type GrasshopperParsedIO, type GrasshopperParsedIORaw, type GrasshopperRequestSchema, GrasshopperResponseProcessor, type InnerTreeData, type InputParam, type InputParamSchema, type NumericInputType, type OutputParamSchema, type OutputType, type ParsedContext, type ProcessedFile, type RhinoModelUnit, type SchedulerMode, type SchemaEndpointResult, type SelvaEventTarget, type SelvaResponseBlock, type SolveContext, type SolveDefinition, type SolveOptions, type SolveResult, type SolveSchedulerOptions, type TextInputType, type ValueListInputType, downloadFileData, extractFilesFromComputeResponse, isDefinitionRef };
|
|
1334
|
+
export { type BooleanInputType, type CacheOptions, type CacheStats, type ColorInputType, ComputeServerStats, type CreateClientOptions, type DataItem, type DataTree, type DataTreeDefault, type DataTreePath, type DataTreeValue, type DefaultValue, type FileInputType, type GeometryInputType, type GetValuesOptions, type GetValuesResult, GrasshopperClient, type GrasshopperComputeConfig, type GrasshopperComputeResponse, type GrasshopperParsedIO, type GrasshopperParsedIORaw, GrasshopperResponseProcessor, type InnerTreeData, type InputParam, type InputParamSchema, type InputParseError, type NumericInputType, type OutputParamSchema, type ParsedContext, type RhinoDecodeError, type RhinoModelUnit, type RhinoRuntime, type SchedulerMode, type SchedulerSolveOptions, type SchemaEndpointResult, type SelvaEventTarget, type SelvaResponseBlock, type ServerLimits, type ServerStats, type ServerVersion, type SolveContext, type SolveDetail, type SolveExecutor, type SolveOptions, type SolveResult, type SolveSchedulerOptions, type TextInputType, type TreeValueEntry, type ValueListInputType };
|
|
1790
1335
|
//# sourceMappingURL=grasshopper.d.ts.map
|