@selvajs/solve 2.0.0-beta.11 → 2.0.0-beta.12
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 +16 -10
- package/dist/abort-CNJ8Sn4g.js +13 -0
- package/dist/abort-CNJ8Sn4g.js.map +1 -0
- package/dist/client.d.ts +33 -134
- package/dist/client.js +335 -240
- package/dist/client.js.map +1 -1
- package/dist/{outcome-DsNmx27P.d.ts → outcome-Bk9mnMi0.d.ts} +9 -28
- package/dist/{outcome-ai_9fm43.js → outcome-DNrffAXp.js} +48 -46
- package/dist/outcome-DNrffAXp.js.map +1 -0
- package/dist/server.d.ts +73 -222
- package/dist/server.js +594 -419
- package/dist/server.js.map +1 -1
- package/dist/shared.d.ts +2 -2
- package/dist/shared.js +1 -1
- package/package.json +5 -13
- package/dist/outcome-ai_9fm43.js.map +0 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ This package owns everything between those two points. Nothing else.
|
|
|
19
19
|
| ----------------------- | ----------------------- |
|
|
20
20
|
| A web page with sliders | `@selvajs/solve/client` |
|
|
21
21
|
| An API endpoint | `@selvajs/solve/server` |
|
|
22
|
-
|
|
|
22
|
+
| Types and verdict logic | `@selvajs/solve/shared` |
|
|
23
23
|
|
|
24
24
|
There is no `.` export on purpose — see [Why no root export](#why-no-root-export).
|
|
25
25
|
|
|
@@ -157,15 +157,17 @@ if rebuilt per request.
|
|
|
157
157
|
// $lib/server/compute/engine.server.ts
|
|
158
158
|
import { SolveEngine } from '@selvajs/solve/server';
|
|
159
159
|
|
|
160
|
-
export const engine = new SolveEngine({ limits: computeLimits
|
|
160
|
+
export const engine = new SolveEngine({ limits: computeLimits });
|
|
161
161
|
```
|
|
162
162
|
|
|
163
163
|
```ts
|
|
164
164
|
// routes/api/v1/compute/+server.ts
|
|
165
|
+
import { solveInputsFromSchema } from '@selvajs/solve/server';
|
|
166
|
+
|
|
165
167
|
const outcome = await engine.solve({
|
|
166
168
|
server: serverConfig, // which Rhino.Compute
|
|
167
169
|
definitionSource, // the .gh file (bytes, URL, or cached ref)
|
|
168
|
-
inputs, // the
|
|
170
|
+
inputs: solveInputsFromSchema(storedSchema), // yours, never the request's
|
|
169
171
|
values, // what the browser sent
|
|
170
172
|
signal: request.signal, // client disconnects → cancel upstream
|
|
171
173
|
acceptEncoding: request.headers.get('accept-encoding') ?? ''
|
|
@@ -174,6 +176,9 @@ const outcome = await engine.solve({
|
|
|
174
176
|
return engine.toWebResponse(outcome);
|
|
175
177
|
```
|
|
176
178
|
|
|
179
|
+
Read `inputs` from the schema you stored. A request that supplies them picks the ids, types and
|
|
180
|
+
bounds that reach the definition: it can drop a limit or fill a slot your host reserved.
|
|
181
|
+
|
|
177
182
|
`solve()` doesn't throw for an expected failure. It returns one of these, so you can branch before
|
|
178
183
|
handing it to `toWebResponse`:
|
|
179
184
|
|
|
@@ -197,11 +202,11 @@ return engine.toWebResponse(outcome);
|
|
|
197
202
|
engine.solve()
|
|
198
203
|
│
|
|
199
204
|
├─ 1. warm client cache ····· reuse the open Rhino.Compute connection
|
|
200
|
-
├─ 2.
|
|
205
|
+
├─ 2. build input tree ······ values → Grasshopper DataTree
|
|
201
206
|
├─ 3. single-flight ········· 5 users, same inputs → 1 actual solve
|
|
202
|
-
├─ 4.
|
|
207
|
+
├─ 4. definition bytes ······ already uploaded? send a pointer, not the .gh
|
|
203
208
|
├─ 5. SOLVE ················· the only slow step
|
|
204
|
-
└─ 6. gzip + Server-Timing ··
|
|
209
|
+
└─ 6. gzip + Server-Timing ·· one envelope per caller
|
|
205
210
|
```
|
|
206
211
|
|
|
207
212
|
Each layer is covered in [`src/server/README.md`](./src/server/README.md).
|
|
@@ -244,8 +249,8 @@ solve needs.
|
|
|
244
249
|
|
|
245
250
|
## Why no root export
|
|
246
251
|
|
|
247
|
-
`server/` uses `node:zlib
|
|
248
|
-
|
|
252
|
+
`server/` uses `node:zlib` and `undici`, and holds compute-server credentials. A `.` barrel joining
|
|
253
|
+
both halves would let a browser bundle pull all of that in by accident.
|
|
249
254
|
|
|
250
255
|
```
|
|
251
256
|
shared/ the types both sides speak
|
|
@@ -253,7 +258,8 @@ joining both halves would let a browser bundle pull all of that in by accident.
|
|
|
253
258
|
client/ server/ never import each other
|
|
254
259
|
```
|
|
255
260
|
|
|
256
|
-
Enforced by `no-restricted-imports` and a bundle-boundary test, not by
|
|
261
|
+
Enforced by `no-restricted-imports`, a `tsc` pass per half and a bundle-boundary test, not by
|
|
262
|
+
convention.
|
|
257
263
|
|
|
258
264
|
## Not in this package
|
|
259
265
|
|
|
@@ -267,4 +273,4 @@ Enforced by `no-restricted-imports` and a bundle-boundary test, not by conventio
|
|
|
267
273
|
## Going deeper
|
|
268
274
|
|
|
269
275
|
- [`src/client/README.md`](./src/client/README.md) — writing your own driver, the value map, mesh ownership
|
|
270
|
-
- [`src/server/README.md`](./src/server/README.md) — cache layers, coalescing,
|
|
276
|
+
- [`src/server/README.md`](./src/server/README.md) — cache layers, coalescing, encoding
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/shared/abort.ts
|
|
2
|
+
/** `promise`'s outcome, or a rejection with `signal`'s reason if that fires first. */
|
|
3
|
+
function raceAbort(promise, signal) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const onAbort = () => reject(signal.reason);
|
|
6
|
+
if (signal.aborted) onAbort();
|
|
7
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
8
|
+
promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export { raceAbort as t };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=abort-CNJ8Sn4g.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abort-CNJ8Sn4g.js","names":[],"sources":["../src/shared/abort.ts"],"sourcesContent":["/** `promise`'s outcome, or a rejection with `signal`'s reason if that fires first. */\nexport function raceAbort<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst onAbort = () => reject(signal.reason);\n\t\tif (signal.aborted) onAbort();\n\t\tsignal.addEventListener('abort', onAbort, { once: true });\n\t\tpromise.then(resolve, reject).finally(() => signal.removeEventListener('abort', onAbort));\n\t});\n}\n"],"mappings":";;AACA,SAAgB,UAAa,SAAqB,QAAiC;CAClF,OAAO,IAAI,SAAS,SAAS,WAAW;EACvC,MAAM,gBAAgB,OAAO,OAAO,MAAM;EAC1C,IAAI,OAAO,SAAS,QAAQ;EAC5B,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;EACxD,QAAQ,KAAK,SAAS,MAAM,CAAC,CAAC,cAAc,OAAO,oBAAoB,SAAS,OAAO,CAAC;CACzF,CAAC;AACF"}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ProgressPayload, SolveEvent, UISchema } from "@selvajs/schemas";
|
|
1
|
+
import { a as SolveFn, i as SolveDiagnostic, n as decodeOutcome, o as SolveResult, r as finalizeResult, t as SolveOutcome } from "./outcome-Bk9mnMi0.js";
|
|
2
|
+
import { ProgressPayload, SolveEndedKind, SolveEvent, UISchema } from "@selvajs/schemas";
|
|
3
3
|
import { GrasshopperComputeResponse } from "@selvajs/compute/grasshopper";
|
|
4
4
|
/**
|
|
5
5
|
* Transport behind a solve session. `solve()` never returns outputs directly — results
|
|
@@ -31,11 +31,12 @@ interface SolveDriver {
|
|
|
31
31
|
*/
|
|
32
32
|
readonly hasQueued?: boolean;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
* Forgets the current definition: stops its running solve, drops its cached results, and
|
|
35
|
+
* never reports for it again. The session calls this on rebuild and dispose, where a late
|
|
36
|
+
* result would land in the wrong definition. Optional: a push transport leaves it out, because
|
|
37
|
+
* the solve it would stop belongs to the Grasshopper canvas, not to this session.
|
|
37
38
|
*/
|
|
38
|
-
|
|
39
|
+
reset?(): void;
|
|
39
40
|
/**
|
|
40
41
|
* Live events from the running solve, when the transport carries them (a WebSocket frame
|
|
41
42
|
* locally, an SSE stream in cloud mode). Returns the unsubscribe. A driver without a live
|
|
@@ -69,9 +70,9 @@ interface LiveSolveState {
|
|
|
69
70
|
readonly diagnostics: readonly SolveDiagnostic[];
|
|
70
71
|
/** The newest `progress` per source. A report without a source is keyed by `''`. */
|
|
71
72
|
readonly progress: ReadonlyMap<string, ProgressPayload>;
|
|
72
|
-
/** `solveEnded`'s payload once it arrives
|
|
73
|
+
/** `solveEnded`'s payload once it arrives. */
|
|
73
74
|
readonly ended: {
|
|
74
|
-
readonly kind:
|
|
75
|
+
readonly kind: SolveEndedKind;
|
|
75
76
|
} | null;
|
|
76
77
|
/** Events of kinds this package does not know, oldest first. */
|
|
77
78
|
readonly other: readonly SolveEvent[];
|
|
@@ -79,7 +80,6 @@ interface LiveSolveState {
|
|
|
79
80
|
readonly lastSeq: number;
|
|
80
81
|
}
|
|
81
82
|
export declare const EMPTY_LIVE_SOLVE: LiveSolveState;
|
|
82
|
-
export declare function reduceLiveSolve(state: LiveSolveState, event: SolveEvent): LiveSolveState;
|
|
83
83
|
interface ExternalValueRef {
|
|
84
84
|
scopeKey: string;
|
|
85
85
|
inputId: string;
|
|
@@ -105,79 +105,7 @@ export declare function getExternalInputs(schema: UISchema): ExternalInput[];
|
|
|
105
105
|
* live meshes stay on `session.meshes`.
|
|
106
106
|
*/
|
|
107
107
|
type RetainedSolveResult<TSource = unknown> = Omit<SolveResult<never, TSource>, 'meshes'>;
|
|
108
|
-
interface SolveSessionState {
|
|
109
|
-
values: Record<string, unknown>;
|
|
110
|
-
error: string;
|
|
111
|
-
computeErrors: string[];
|
|
112
|
-
computeWarnings: string[];
|
|
113
|
-
/**
|
|
114
|
-
* The same messages with their level, source and `isGate`. What decides whether a solve
|
|
115
|
-
* interrupts the user; the two string arrays above stay the plain display lists.
|
|
116
|
-
*/
|
|
117
|
-
diagnostics: SolveDiagnostic[];
|
|
118
|
-
/**
|
|
119
|
-
* The last solve was refused by a guard in the definition. Separate from `computeErrors`
|
|
120
|
-
* being non-empty: a solve can report errors and still return usable outputs, and the UI
|
|
121
|
-
* needs to tell "solved, with complaints" from "would not solve".
|
|
122
|
-
*/
|
|
123
|
-
blocked: boolean;
|
|
124
|
-
/**
|
|
125
|
-
* The last solve raised messages the user has not acknowledged yet. While true the result
|
|
126
|
-
* is withheld: `meshes` and the solve's outputs stay at their previous values until
|
|
127
|
-
* `acknowledge()` releases them.
|
|
128
|
-
*/
|
|
129
|
-
awaitingAck: boolean;
|
|
130
|
-
/**
|
|
131
|
-
* The withheld result, kept whole so `acknowledge()` can apply it without a re-solve.
|
|
132
|
-
* Null whenever `awaitingAck` is false. A newer solve replaces it: the user is always
|
|
133
|
-
* confirming the most recent result, never a stale one.
|
|
134
|
-
*/
|
|
135
|
-
heldResult: SolveResult | null;
|
|
136
|
-
meshes: unknown[];
|
|
137
|
-
/** Values changed since the last solve, in manual (instanceSolve === false) mode. */
|
|
138
|
-
pendingValues: Record<string, unknown>;
|
|
139
|
-
hasPendingChanges: boolean;
|
|
140
|
-
hasNeverSolved: boolean;
|
|
141
|
-
/**
|
|
142
|
-
* The last result reported, minus its meshes. Null before the first solve.
|
|
143
|
-
*
|
|
144
|
-
* Lags `values` by design: nothing updates it on `setValue` or `loadValues`, so between a
|
|
145
|
-
* value change and the next report it describes the *previous* input set. That is what a
|
|
146
|
-
* commit gate wants — what is on screen, not what is pending — so `lastResult.values`
|
|
147
|
-
* disagreeing with `state.values` mid-scrub is the feature, not a bug.
|
|
148
|
-
*/
|
|
149
|
-
lastResult: RetainedSolveResult | null;
|
|
150
|
-
}
|
|
151
|
-
type ExternalReader = (ref: ExternalValueRef) => unknown | undefined;
|
|
152
|
-
/**
|
|
153
|
-
* Client-sourced inputs are hydrated from `read` and left absent when no stored value
|
|
154
|
-
* exists, so the missing-inputs panel can detect them. Other inputs fall back to their
|
|
155
|
-
* declared default, then the paramType default.
|
|
156
|
-
*/
|
|
157
|
-
export declare function buildInitialValues(schema: UISchema, scopeKey: string, read: ExternalReader): Record<string, unknown>;
|
|
158
|
-
/** Manual-solve schemas (instanceSolve === false) start dirty; auto-solve schemas start clean. */
|
|
159
|
-
export declare function makeInitialFlags(instanceSolve: boolean | undefined): {
|
|
160
|
-
hasPendingChanges: boolean;
|
|
161
|
-
hasNeverSolved: boolean;
|
|
162
|
-
};
|
|
163
|
-
/** Manual mode defers (records the pending value, raises the dirty flag) instead of solving. */
|
|
164
|
-
export declare function applyValueChange(state: SolveSessionState, id: string, value: unknown, instanceSolve: boolean | undefined): {
|
|
165
|
-
state: SolveSessionState;
|
|
166
|
-
shouldSolve: boolean;
|
|
167
|
-
};
|
|
168
|
-
/**
|
|
169
|
-
* Solve outputs live in the same `values` map as inputs (so widgets like dynamic value
|
|
170
|
-
* lists can read them) but must not be echoed back to the driver: a measured 6.4 MB
|
|
171
|
-
* options-list output showed this can re-upload a multi-MB payload no backend reads.
|
|
172
|
-
*/
|
|
173
|
-
export declare function pickInputValues(schema: UISchema | undefined, values: Record<string, unknown>): Record<string, unknown>;
|
|
174
|
-
export declare function applySolveResult(state: SolveSessionState, result: SolveResult): SolveSessionState;
|
|
175
108
|
type SolvePhase = 'idle' | 'solving' | 'review' | 'blocked';
|
|
176
|
-
/**
|
|
177
|
-
* One value for what a host should show. Solving wins: a new solve supersedes a held or refused
|
|
178
|
-
* result. `isSolving` is passed in because the driver owns it.
|
|
179
|
-
*/
|
|
180
|
-
export declare function solvePhase(state: SolveSessionState, isSolving: boolean): SolvePhase;
|
|
181
109
|
/**
|
|
182
110
|
* How a solve ended, once nothing about it can change any more: a held result counts only
|
|
183
111
|
* after the user accepts or rejects it, and a result a queued solve is about to replace never
|
|
@@ -188,7 +116,7 @@ type SolveSettlement = {
|
|
|
188
116
|
result: RetainedSolveResult;
|
|
189
117
|
diagnostics: SolveDiagnostic[];
|
|
190
118
|
} |
|
|
191
|
-
/**
|
|
119
|
+
/** A held result the user rejected or a newer solve replaced; the screen still shows the one before it. */
|
|
192
120
|
{
|
|
193
121
|
status: 'discarded';
|
|
194
122
|
diagnostics: SolveDiagnostic[];
|
|
@@ -262,10 +190,10 @@ interface SolveSession {
|
|
|
262
190
|
abort(): void;
|
|
263
191
|
readonly meshes: unknown[];
|
|
264
192
|
/**
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
193
|
+
* What the viewer is currently showing, including the `source`/`values` pair a commit path
|
|
194
|
+
* needs. Null before the first solve, and again after `rebuild()`. Survives `reportError`: a
|
|
195
|
+
* failed solve leaves the last good geometry on screen, so a host committing what it sees
|
|
196
|
+
* should still see what produced it.
|
|
269
197
|
*/
|
|
270
198
|
readonly lastResult: RetainedSolveResult | null;
|
|
271
199
|
readonly hasPendingChanges: boolean;
|
|
@@ -282,7 +210,8 @@ interface SolveSession {
|
|
|
282
210
|
/**
|
|
283
211
|
* The result for the current inputs, solving only when it has to: right away from the result
|
|
284
212
|
* on screen when nothing changed, after the running or held solve when there is one, else
|
|
285
|
-
* after a new solve. For an action that needs a fresh result, such as an export.
|
|
213
|
+
* after a new solve. For an action that needs a fresh result, such as an export. Inputs whose
|
|
214
|
+
* result the user just discarded settle as `discarded` rather than ask them again.
|
|
286
215
|
*/
|
|
287
216
|
ensureSolved(): Promise<SolveSettlement>;
|
|
288
217
|
/** Fires once per settled solve, the ones input changes start included. Returns the unsubscribe. */
|
|
@@ -298,9 +227,9 @@ interface SolveSession {
|
|
|
298
227
|
/** For driver-owned state the session only forwards: `isSolving` lives on the driver, so wire this to its `onChange`. */
|
|
299
228
|
notify(): void;
|
|
300
229
|
/**
|
|
301
|
-
*
|
|
302
|
-
* session is discarded: the event source can outlive it (the cloud stream belongs to the
|
|
303
|
-
* and would otherwise keep feeding a session nobody reads.
|
|
230
|
+
* Resets the driver, stops listening to its live events and drops every subscriber. Call when
|
|
231
|
+
* the session is discarded: the event source can outlive it (the cloud stream belongs to the
|
|
232
|
+
* tab), and would otherwise keep feeding a session nobody reads. Inert afterwards.
|
|
304
233
|
*/
|
|
305
234
|
dispose(): void;
|
|
306
235
|
}
|
|
@@ -312,9 +241,13 @@ interface SolveSessionArgs {
|
|
|
312
241
|
export declare function createSolveSession(args: SolveSessionArgs): SolveSession;
|
|
313
242
|
/**
|
|
314
243
|
* Deterministic string key for a set of input values. Sorts object keys at every level so
|
|
315
|
-
* two logically-equal inputs built in different key order collide.
|
|
244
|
+
* two logically-equal inputs built in different key order collide. Otherwise matches what
|
|
245
|
+
* `JSON.stringify` sends: `toJSON` is honoured and an `undefined` property is absent, which a
|
|
246
|
+
* server treats differently from `null`.
|
|
247
|
+
*
|
|
248
|
+
* Throws on a `bigint`, as `JSON.stringify` does.
|
|
316
249
|
*/
|
|
317
|
-
export declare function stableInputKey(
|
|
250
|
+
export declare function stableInputKey(input: unknown): string;
|
|
318
251
|
/**
|
|
319
252
|
* Omit when results are mesh-free or nothing takes ownership of the meshes — the memo then
|
|
320
253
|
* stores and serves them by reference, which is safe only because nothing frees them behind
|
|
@@ -326,17 +259,6 @@ interface MeshPolicy<TMesh> {
|
|
|
326
259
|
/** Must not free anything shared with live content (e.g. materials another object still uses). */
|
|
327
260
|
release(meshes: TMesh[]): void;
|
|
328
261
|
}
|
|
329
|
-
interface SolveMemoOptions<TMesh> {
|
|
330
|
-
/** Entry cap, not a byte cap. Kept small on purpose: this targets the slider-scrub loop, not a durable cache. */
|
|
331
|
-
max?: number;
|
|
332
|
-
meshPolicy?: MeshPolicy<TMesh>;
|
|
333
|
-
}
|
|
334
|
-
interface SolveMemo<TMesh = unknown> {
|
|
335
|
-
get(values: Record<string, unknown>): SolveResult<TMesh> | undefined;
|
|
336
|
-
set(values: Record<string, unknown>, result: SolveResult<TMesh>): void;
|
|
337
|
-
clear(): void;
|
|
338
|
-
}
|
|
339
|
-
export declare function createSolveMemo<TMesh = unknown>(options?: SolveMemoOptions<TMesh>): SolveMemo<TMesh>;
|
|
340
262
|
interface RequestResponseDriverOptions<TMesh> {
|
|
341
263
|
/** How long one solve may take before the client aborts it (ms). Pass the server's `COMPUTE_SOLVE_DEADLINE_MS` so the two agree. */
|
|
342
264
|
solveDeadlineMs: number;
|
|
@@ -363,42 +285,16 @@ interface SolveEventStream extends SolveEventSource {
|
|
|
363
285
|
readonly streamId: string;
|
|
364
286
|
/** The solve the server last reported as started and not yet ended; null between solves. */
|
|
365
287
|
readonly currentSolveId: string | null;
|
|
288
|
+
/** Final: the stream does not reopen, and a later subscriber hears nothing. */
|
|
366
289
|
close(): void;
|
|
367
290
|
}
|
|
368
291
|
export declare function createSolveEventStream(options: SolveEventStreamOptions): SolveEventStream;
|
|
369
|
-
/**
|
|
370
|
-
* Single-in-flight, latest-wins throttle for any async operation: only one run at a
|
|
371
|
-
* time, a newly triggered value overwrites the single pending slot (no queue), and a
|
|
372
|
-
* stale run can be aborted via `AbortController` or timeout.
|
|
373
|
-
*
|
|
374
|
-
* Framework-free: `isRunning` is a plain getter, not a store. A reactive host must
|
|
375
|
-
* subscribe via `onChange` (see `@selvajs/ui`'s rune adapter) — polling the getter
|
|
376
|
-
* directly reads correct values but won't trigger a re-render.
|
|
377
|
-
*/
|
|
378
|
-
interface AsyncThrottleOptions {
|
|
379
|
-
/**
|
|
380
|
-
* How long one run may take before it is aborted (ms). Required and deliberately
|
|
381
|
-
* undefaulted: this is a generic throttle, so it has no basis for guessing what
|
|
382
|
-
* the caller's work costs. Callers driving a Selva solve pass the deadline the
|
|
383
|
-
* server enforces (`COMPUTE_SOLVE_DEADLINE_MS`) — a shorter local guess would abort
|
|
384
|
-
* solves the server would have finished.
|
|
385
|
-
*/
|
|
386
|
-
runDeadlineMs: number;
|
|
387
|
-
onChange?: () => void;
|
|
388
|
-
}
|
|
389
|
-
interface AsyncThrottle<T> {
|
|
390
|
-
trigger: (values: T) => void;
|
|
391
|
-
readonly isRunning: boolean;
|
|
392
|
-
readonly hasPending: boolean;
|
|
393
|
-
cancel: () => void;
|
|
394
|
-
}
|
|
395
|
-
export declare function createAsyncThrottle<T>(run: (values: T, signal: AbortSignal) => Promise<void>, options: AsyncThrottleOptions): AsyncThrottle<T>;
|
|
396
292
|
interface ComputeFetchSolveFnOptions<TMesh = unknown> {
|
|
397
293
|
/** The compute endpoint to POST to, e.g. `/api/compute`. */
|
|
398
294
|
endpoint: string;
|
|
399
295
|
/** Definition URL (or `local:<guid>`) to solve — read per-solve so it can track a route param. */
|
|
400
296
|
definitionUrl: () => string;
|
|
401
|
-
/** Schema input params, sent as the request body's `inputs`. */
|
|
297
|
+
/** Schema input params, sent as the request body's `inputs`. A stored definition's server ignores them. */
|
|
402
298
|
inputs: () => Array<{
|
|
403
299
|
id: string;
|
|
404
300
|
}>;
|
|
@@ -415,15 +311,18 @@ interface ComputeFetchSolveFnOptions<TMesh = unknown> {
|
|
|
415
311
|
meshes?: {
|
|
416
312
|
extract: (response: GrasshopperComputeResponse, opts: {
|
|
417
313
|
debug: boolean;
|
|
314
|
+
signal: AbortSignal;
|
|
418
315
|
}) => TMesh[] | Promise<TMesh[]>;
|
|
419
316
|
};
|
|
420
317
|
/** Gates ALL console telemetry (timing, cache verdicts, whales, heap). Default `false`. */
|
|
421
318
|
debug?: boolean;
|
|
422
|
-
/** Called on a 429
|
|
319
|
+
/** Called on a 429 and on a solve refused during its cooldown, before the rate-limit Error. */
|
|
423
320
|
onRateLimited?: (retryAfterSeconds: number) => void;
|
|
424
|
-
/** Called on a 401 or a login-page redirect
|
|
321
|
+
/** Called on a 401 or a login-page redirect, before the "sign in again" Error. */
|
|
425
322
|
onSessionExpired?: () => void;
|
|
323
|
+
/** Where the server redirects an expired session. Default `/login`. */
|
|
324
|
+
loginPath?: string;
|
|
426
325
|
}
|
|
427
326
|
export declare function createComputeFetchSolveFn<TMesh = unknown>(opts: ComputeFetchSolveFnOptions<TMesh>): SolveFn<TMesh, GrasshopperComputeResponse>;
|
|
428
|
-
export { type
|
|
327
|
+
export { type ComputeFetchSolveFnOptions, type ExternalInput, type ExternalValueRef, type LiveSolveState, type MeshPolicy, type RequestResponseDriverOptions, type RetainedSolveResult, type SolveDiagnostic, type SolveDriver, type SolveEventSource, type SolveEventStream, type SolveEventStreamOptions, type SolveFn, type SolveOutcome, type SolvePhase, type SolveReporter, type SolveResult, type SolveSession, type SolveSessionArgs, type SolveSettlement, decodeOutcome, finalizeResult };
|
|
429
328
|
//# sourceMappingURL=client.d.ts.map
|