@selvajs/compute 5.0.0-beta.7 → 5.0.0-beta.9
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 +30 -11
- package/dist/core.d.ts +190 -2
- package/dist/core.js +1 -1
- package/dist/grasshopper.d.ts +57 -92
- package/dist/grasshopper.js +3051 -1
- package/dist/grasshopper.js.map +1 -1
- package/dist/handle-files-fKtSlWT2.js +1351 -0
- package/dist/handle-files-fKtSlWT2.js.map +1 -0
- package/dist/types-Dm9QFVvA.d.ts +247 -0
- package/package.json +14 -39
- package/dist/core-BPYXUtfq.js +0 -3
- package/dist/core-BPYXUtfq.js.map +0 -1
- package/dist/core-DF0VYOve.cjs +0 -3
- package/dist/core-DF0VYOve.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 -1355
- package/dist/index-DDmprCht.d.cts +0 -421
- package/dist/index-DDmprCht.d.ts +0 -421
package/dist/index-DDmprCht.d.ts
DELETED
|
@@ -1,421 +0,0 @@
|
|
|
1
|
-
declare const ErrorCodes: {
|
|
2
|
-
/** Connection failure, a gateway status (502/503/504), or a 2xx body cut off mid-stream. */
|
|
3
|
-
readonly NETWORK_ERROR: "NETWORK_ERROR";
|
|
4
|
-
/** HTTP 401 or 403: the server rejected the credentials. */
|
|
5
|
-
readonly AUTH_ERROR: "AUTH_ERROR";
|
|
6
|
-
/** The server rejected the request (HTTP 400, 413), or an input failed a client-side check. */
|
|
7
|
-
readonly VALIDATION_ERROR: "VALIDATION_ERROR";
|
|
8
|
-
/** The server failed the solve (HTTP 500), or the solve reported errors. */
|
|
9
|
-
readonly COMPUTATION_ERROR: "COMPUTATION_ERROR";
|
|
10
|
-
/** No response within `ComputeConfig.timeoutMs`. */
|
|
11
|
-
readonly TIMEOUT_ERROR: "TIMEOUT_ERROR";
|
|
12
|
-
/** A browser fetch failed with no response: most often CORS, which the browser hides. */
|
|
13
|
-
readonly CORS_ERROR: "CORS_ERROR";
|
|
14
|
-
/** HTTP 404: the endpoint doesn't exist on this server. Never retried. */
|
|
15
|
-
readonly NOT_FOUND: "NOT_FOUND";
|
|
16
|
-
/** HTTP 429. Retried, honouring `Retry-After`, when the policy allows (`RetryPolicy.retryOn429`). */
|
|
17
|
-
readonly RATE_LIMIT: "RATE_LIMIT";
|
|
18
|
-
/** A 2xx that declared a non-JSON body, e.g. a captive portal or proxy login page. Never retried. */
|
|
19
|
-
readonly INVALID_RESPONSE: "INVALID_RESPONSE";
|
|
20
|
-
/**
|
|
21
|
-
* The response body passed `ComputeConfig.maxResponseBytes`; the download was cancelled there.
|
|
22
|
-
* Never retried. `context` carries `{ maxResponseBytes }`.
|
|
23
|
-
*/
|
|
24
|
-
readonly RESPONSE_TOO_LARGE: "RESPONSE_TOO_LARGE";
|
|
25
|
-
/** Any failure not classified by another code. */
|
|
26
|
-
readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
|
|
27
|
-
/** An object was used after `dispose()`, or a file download failed part-way. */
|
|
28
|
-
readonly INVALID_STATE: "INVALID_STATE";
|
|
29
|
-
/** A caller-supplied argument is unusable: an empty definition, an unserializable body. */
|
|
30
|
-
readonly INVALID_INPUT: "INVALID_INPUT";
|
|
31
|
-
/**
|
|
32
|
-
* Bad configuration: an invalid `serverUrl`, a server that answers with a redirect, an
|
|
33
|
-
* incomplete logger, an interval out of range.
|
|
34
|
-
*/
|
|
35
|
-
readonly INVALID_CONFIG: "INVALID_CONFIG";
|
|
36
|
-
/** A browser-only API (file download) was called outside a browser. */
|
|
37
|
-
readonly BROWSER_ONLY: "BROWSER_ONLY";
|
|
38
|
-
/** The runtime has no base64 codec: neither `Buffer` nor `atob`/`btoa`. */
|
|
39
|
-
readonly ENVIRONMENT_ERROR: "ENVIRONMENT_ERROR";
|
|
40
|
-
/** A string that should be base64 isn't. */
|
|
41
|
-
readonly ENCODING_ERROR: "ENCODING_ERROR";
|
|
42
|
-
/** An input's `default` had a shape the normalizer didn't recognize. */
|
|
43
|
-
readonly MALFORMED_DEFAULT: "MALFORMED_DEFAULT";
|
|
44
|
-
/** Latest-wins scheduling: a newer call replaced this one. */
|
|
45
|
-
readonly SUPERSEDED: "SUPERSEDED";
|
|
46
|
-
/** The scheduler or a caller-supplied `AbortSignal` aborted this call. */
|
|
47
|
-
readonly ABORTED: "ABORTED";
|
|
48
|
-
/**
|
|
49
|
-
* The queue was at `maxQueueDepth`, so the call was rejected without queueing. Retryable after a
|
|
50
|
-
* back-off. `context` carries `{ queueDepth, maxQueueDepth }`.
|
|
51
|
-
*/
|
|
52
|
-
readonly QUEUE_FULL: "QUEUE_FULL";
|
|
53
|
-
/**
|
|
54
|
-
* The call waited longer than `queueWaitMs` without starting, and was rejected rather than run
|
|
55
|
-
* stale. Retryable. `context` carries `{ waitedMs, queueWaitMs }`.
|
|
56
|
-
*/
|
|
57
|
-
readonly QUEUE_TIMEOUT: "QUEUE_TIMEOUT";
|
|
58
|
-
/**
|
|
59
|
-
* The server no longer holds the definition a `pointer` named (evicted, restarted, another
|
|
60
|
-
* child). Retry with the full definition. Read from the error body's
|
|
61
|
-
* `code: "definition_not_cached"`.
|
|
62
|
-
*/
|
|
63
|
-
readonly DEFINITION_NOT_CACHED: "DEFINITION_NOT_CACHED";
|
|
64
|
-
};
|
|
65
|
-
type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
66
|
-
/** Error with a typed `code`: switch on it rather than on the message. */
|
|
67
|
-
declare class ComputeError extends Error {
|
|
68
|
-
readonly code: ErrorCode;
|
|
69
|
-
readonly statusCode?: number;
|
|
70
|
-
readonly context?: Record<string, unknown>;
|
|
71
|
-
readonly originalError?: Error;
|
|
72
|
-
constructor(message: string, code?: ErrorCode, options?: {
|
|
73
|
-
statusCode?: number;
|
|
74
|
-
context?: Record<string, unknown>;
|
|
75
|
-
originalError?: unknown;
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
/** A backend's error-body `code` → one of our {@link ErrorCodes}. */
|
|
79
|
-
type ServerErrorCodeMap = Record<string, ErrorCode>;
|
|
80
|
-
/**
|
|
81
|
-
* Exponential backoff with jitter; a server `Retry-After` replaces the backoff for that attempt.
|
|
82
|
-
*
|
|
83
|
-
* Requests are POSTs: a connection lost after the body was sent may already have run on the
|
|
84
|
-
* server, and the retry runs it again. A solve is deterministic, so that wastes work but corrupts
|
|
85
|
-
* nothing; a non-idempotent endpoint should keep `attempts: 0`.
|
|
86
|
-
*/
|
|
87
|
-
interface RetryPolicy {
|
|
88
|
-
/** Maximum number of retry attempts after the initial request (default: 0). */
|
|
89
|
-
attempts?: number;
|
|
90
|
-
/** Base delay in milliseconds for exponential backoff (default: 500). */
|
|
91
|
-
baseDelayMs?: number;
|
|
92
|
-
/** Upper bound for backoff delay (default: 30_000). */
|
|
93
|
-
maxDelayMs?: number;
|
|
94
|
-
/** Whether to retry on 429 responses (default: true — honors Retry-After). */
|
|
95
|
-
retryOn429?: boolean;
|
|
96
|
-
}
|
|
97
|
-
interface ComputeConfig {
|
|
98
|
-
serverUrl: string;
|
|
99
|
-
/** Optional API key for authenticating with the server. Sent as {@link apiKeyHeader}. */
|
|
100
|
-
apiKey?: string;
|
|
101
|
-
/**
|
|
102
|
-
* Header name carrying `apiKey`. Defaults to `'RhinoComputeKey'` — the name
|
|
103
|
-
* rhino.compute expects. A different backend sets its own.
|
|
104
|
-
*/
|
|
105
|
-
apiKeyHeader?: string;
|
|
106
|
-
/** Sent verbatim as the `Authorization` header, so include the scheme (`Bearer …`). */
|
|
107
|
-
authToken?: string;
|
|
108
|
-
/**
|
|
109
|
-
* Extra request headers, e.g. routing hints a reverse proxy reads. A header the transport sets
|
|
110
|
-
* (credentials, `X-Request-ID`, `Content-Type`) wins over a caller header of any casing.
|
|
111
|
-
*/
|
|
112
|
-
headers?: Record<string, string>;
|
|
113
|
-
/** Log each request at debug level through the configured logger (see `setLogger`). */
|
|
114
|
-
debug?: boolean;
|
|
115
|
-
/** Silence the warning logged when a call that carries the API key runs in a browser. */
|
|
116
|
-
suppressBrowserWarning?: boolean;
|
|
117
|
-
/**
|
|
118
|
-
* Per-attempt timeout, re-armed on every retry: the worst case is `(attempts + 1) × timeoutMs`
|
|
119
|
-
* plus backoff. Pass `signal` for an overall deadline.
|
|
120
|
-
*/
|
|
121
|
-
timeoutMs?: number;
|
|
122
|
-
/** Retry policy for transient errors. Default: no retries. */
|
|
123
|
-
retry?: RetryPolicy;
|
|
124
|
-
/**
|
|
125
|
-
* Cancels the request, including during a retry backoff. Composes with `timeoutMs`: whichever
|
|
126
|
-
* fires first wins.
|
|
127
|
-
*/
|
|
128
|
-
signal?: AbortSignal;
|
|
129
|
-
/**
|
|
130
|
-
* Largest response body, in UTF-8 bytes, read before the download is cancelled with
|
|
131
|
-
* `RESPONSE_TOO_LARGE`. A Grasshopper solve leaves out the uploaded definition the server echoes
|
|
132
|
-
* back. Default: no limit.
|
|
133
|
-
*/
|
|
134
|
-
maxResponseBytes?: number;
|
|
135
|
-
/**
|
|
136
|
-
* Maps the `code` field of this backend's JSON error bodies to our {@link ErrorCodes}. A listed
|
|
137
|
-
* code outranks the status-based mapping: the server's production mode scrubs the human message
|
|
138
|
-
* but not the code. Core knows no backend's codes; the client supplies its own table.
|
|
139
|
-
*/
|
|
140
|
-
serverErrorCodes?: ServerErrorCodeMap;
|
|
141
|
-
/**
|
|
142
|
-
* Called with the server's `Server-Timing` breakdown when the response carries a recognised
|
|
143
|
-
* metric, including on a 500 partial success. `requestId` matches the `X-Request-ID` header.
|
|
144
|
-
* A throwing callback doesn't fail the request.
|
|
145
|
-
*/
|
|
146
|
-
onServerTiming?: (timing: ServerTiming, requestId: string) => void;
|
|
147
|
-
}
|
|
148
|
-
/** The config fields that decide how a request authenticates. */
|
|
149
|
-
type ComputeAuth = Pick<ComputeConfig, 'apiKey' | 'apiKeyHeader' | 'authToken' | 'headers'>;
|
|
150
|
-
/** The solve endpoint's `Server-Timing`, durations in ms. `raw` keeps the whole header, unrecognised metrics included. */
|
|
151
|
-
interface ServerTiming {
|
|
152
|
-
decode?: number;
|
|
153
|
-
solve?: number;
|
|
154
|
-
encode?: number;
|
|
155
|
-
/** The part of `solve` spent inside Grasshopper; the rest collects the outputs. */
|
|
156
|
-
gh?: number;
|
|
157
|
-
/** Objects the solve ran out of all it holds. Few ran when only a downstream input changed. */
|
|
158
|
-
recomputed?: {
|
|
159
|
-
ran: number;
|
|
160
|
-
total: number;
|
|
161
|
-
};
|
|
162
|
-
/** The server answered from its result cache and solved nothing. */
|
|
163
|
-
cacheHit?: boolean;
|
|
164
|
-
raw: string;
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* POST `args` as JSON to `<serverUrl>/<endpoint>` with retry, timeout and abort handling, and
|
|
168
|
-
* return the parsed response. Most callers want a higher-level API.
|
|
169
|
-
*
|
|
170
|
-
* `R` names the expected response shape; nothing checks it, so the default `unknown` forces a
|
|
171
|
-
* narrowing.
|
|
172
|
-
*
|
|
173
|
-
* @example
|
|
174
|
-
* const response = await fetchCompute('grasshopper', args, {
|
|
175
|
-
* serverUrl: 'https://my-server.com',
|
|
176
|
-
* timeoutMs: 30_000,
|
|
177
|
-
* retry: { attempts: 2 },
|
|
178
|
-
* signal: controller.signal
|
|
179
|
-
* });
|
|
180
|
-
*/
|
|
181
|
-
declare function fetchCompute<R = unknown>(endpoint: string, args: Record<string, any>, config: ComputeConfig): Promise<R>;
|
|
182
|
-
interface Logger {
|
|
183
|
-
debug(message: string, ...args: unknown[]): void;
|
|
184
|
-
info(message: string, ...args: unknown[]): void;
|
|
185
|
-
warn(message: string, ...args: unknown[]): void;
|
|
186
|
-
error(message: string, ...args: unknown[]): void;
|
|
187
|
-
}
|
|
188
|
-
declare function getLogger(): Logger;
|
|
189
|
-
/**
|
|
190
|
-
* Route the package's logs to `logger`; `null` silences them (the default).
|
|
191
|
-
*
|
|
192
|
-
* @throws {ComputeError} `INVALID_CONFIG` if the logger lacks one of the four methods, rather
|
|
193
|
-
* than a "debug is not a function" later at an unrelated call site.
|
|
194
|
-
*
|
|
195
|
-
* @example
|
|
196
|
-
* ```typescript
|
|
197
|
-
* import { setLogger } from '@selvajs/compute/core';
|
|
198
|
-
*
|
|
199
|
-
* setLogger(console);
|
|
200
|
-
* setLogger({
|
|
201
|
-
* debug: (msg, ...args) => myLogger.debug(msg, ...args),
|
|
202
|
-
* info: (msg, ...args) => myLogger.info(msg, ...args),
|
|
203
|
-
* warn: (msg, ...args) => myLogger.warn(msg, ...args),
|
|
204
|
-
* error: (msg, ...args) => myLogger.error(msg, ...args)
|
|
205
|
-
* });
|
|
206
|
-
* setLogger(null);
|
|
207
|
-
* ```
|
|
208
|
-
*/
|
|
209
|
-
declare function setLogger(logger: Logger | Console | null): void;
|
|
210
|
-
/** Shorthand for `setLogger(console)`. */
|
|
211
|
-
declare function enableDebugLogging(): void;
|
|
212
|
-
/**
|
|
213
|
-
* Case-insensitive field reads for wire payloads.
|
|
214
|
-
*
|
|
215
|
-
* Rhino Compute branches serialize the same field in different casings. mcneel 8.x/9.x send the IO
|
|
216
|
-
* schema PascalCase (`ParamType`, `Default`, `InnerTree`): those C# classes carry no
|
|
217
|
-
* `[JsonProperty]`. The VektorNode fork sends camelCase, except inside the `default` DataTree
|
|
218
|
-
* (`ParamName`, `InnerTree`), an external type it can't attribute. So one response can mix casings.
|
|
219
|
-
* Read the fields you need through here and leave the rest verbatim: rewriting every key corrupts
|
|
220
|
-
* user-authored ones such as value-list labels.
|
|
221
|
-
*/
|
|
222
|
-
/**
|
|
223
|
-
* Read `name` in any casing, preferring an exact-case match. `undefined` when no own key matches or
|
|
224
|
-
* `obj` isn't an object.
|
|
225
|
-
*/
|
|
226
|
-
declare function readField<T = unknown>(obj: unknown, name: string): T | undefined;
|
|
227
|
-
/** Whether `name` is present in any casing, even with a null or undefined value. */
|
|
228
|
-
declare function hasField(obj: unknown, name: string): boolean;
|
|
229
|
-
/**
|
|
230
|
-
* Decode base64 to bytes, normalizing and validating the same way in Node and browsers.
|
|
231
|
-
* `packages/visualization/src/shared/encoding.ts` keeps a copy that throws its own error class;
|
|
232
|
-
* change both together.
|
|
233
|
-
*
|
|
234
|
-
* @throws {ComputeError} `ENCODING_ERROR` if invalid, or `ENVIRONMENT_ERROR` if the runtime has no decoder
|
|
235
|
-
*/
|
|
236
|
-
declare function decodeBase64ToBinary(base64File: string): Uint8Array;
|
|
237
|
-
/** A definition identified by a stable key, with its bytes loaded only when an upload is unavoidable. */
|
|
238
|
-
interface DefinitionRef {
|
|
239
|
-
/**
|
|
240
|
-
* Identity of immutable bytes, such as a version UUID; never a mutable name or path. Every
|
|
241
|
-
* cache trusts the key without looking at the bytes, so two contents sharing a key are served
|
|
242
|
-
* each other's solves, with no diagnostic.
|
|
243
|
-
*/
|
|
244
|
-
key: string;
|
|
245
|
-
/** Called when the solve runs, not when it is scheduled: a solve aborted while queued never loads. */
|
|
246
|
-
load: () => Promise<Uint8Array>;
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* A URL is sent as a pointer, a string is uploaded as base64 (or encoded text), bytes are
|
|
250
|
-
* uploaded as-is. Strings and bytes are content-hashed for caching; a `DefinitionRef` is keyed
|
|
251
|
-
* by its `key`.
|
|
252
|
-
*/
|
|
253
|
-
type SolveDefinition = string | Uint8Array | DefinitionRef;
|
|
254
|
-
declare function isDefinitionRef(definition: SolveDefinition): definition is DefinitionRef;
|
|
255
|
-
/**
|
|
256
|
-
* The public McNeel endpoint, blocked by default: users must point at their own server. Its raw IP
|
|
257
|
-
* isn't blocked: it sits behind a load balancer with no stable address to pin.
|
|
258
|
-
*/
|
|
259
|
-
declare const DEFAULT_BLOCKED_HOST = "compute.rhino3d.com";
|
|
260
|
-
interface ValidateServerUrlOptions {
|
|
261
|
-
/**
|
|
262
|
-
* Hostnames rejected as a `serverUrl` — a backend's shared public endpoint,
|
|
263
|
-
* which callers must not point at. Defaults to `[DEFAULT_BLOCKED_HOST]`; pass
|
|
264
|
-
* `[]` to block nothing. Compared lowercased with any trailing dot stripped.
|
|
265
|
-
*/
|
|
266
|
-
blockedHosts?: readonly string[];
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Validate a compute `serverUrl` and return it trimmed, without trailing slashes. Every entry point
|
|
270
|
-
* that takes a server URL calls this, so a URL is accepted or rejected the same way everywhere.
|
|
271
|
-
*
|
|
272
|
-
* @throws {ComputeError} `INVALID_CONFIG` when the URL is empty, isn't http(s), doesn't parse,
|
|
273
|
-
* embeds credentials, has a query or fragment, or names a blocked host.
|
|
274
|
-
*/
|
|
275
|
-
declare function validateServerUrl(raw: string, options?: ValidateServerUrlOptions): string;
|
|
276
|
-
/**
|
|
277
|
-
* Why a liveness probe failed, and whether waiting can change the answer.
|
|
278
|
-
*
|
|
279
|
-
* `retryable` is the whole point: a powered-off VM and a booting one both read
|
|
280
|
-
* as "offline" from a single probe, but only one of them will ever come up. A
|
|
281
|
-
* caller that can't tell them apart has to assume the optimistic case and burn
|
|
282
|
-
* its full retry window on a machine that is simply off.
|
|
283
|
-
*/
|
|
284
|
-
type ProbeVerdict =
|
|
285
|
-
/** Nothing is listening on the port — the host answered, and said no. */
|
|
286
|
-
'refused' |
|
|
287
|
-
/** The hostname does not resolve. */
|
|
288
|
-
'dns' |
|
|
289
|
-
/** No answer within the timeout: a booting host swallows packets rather than refusing them. */
|
|
290
|
-
'timeout' |
|
|
291
|
-
/** The server answered, but rejected the probe's credentials (401/403). */
|
|
292
|
-
'unauthorized' |
|
|
293
|
-
/** The server answered with a non-2xx that isn't an auth rejection. */
|
|
294
|
-
'http_error' |
|
|
295
|
-
/** Connection failed in a way we can't attribute. */
|
|
296
|
-
'unknown';
|
|
297
|
-
interface ProbeFailure {
|
|
298
|
-
verdict: ProbeVerdict;
|
|
299
|
-
/** Whether retrying the same probe could plausibly succeed later. */
|
|
300
|
-
retryable: boolean;
|
|
301
|
-
/** Operator-facing sentence. Never includes the API key. */
|
|
302
|
-
summary: string;
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Classify a {@link ComputeServerStats.probeServer} result.
|
|
306
|
-
*
|
|
307
|
-
* A DNS failure is treated as retryable even though a missing record won't fix
|
|
308
|
-
* itself: `EAI_AGAIN` is a *timeout* talking to the resolver, and the two are
|
|
309
|
-
* not distinguishable from the error alone. Retrying a genuinely-wrong hostname
|
|
310
|
-
* costs one window; giving up on a resolver hiccup breaks a server that is fine.
|
|
311
|
-
*
|
|
312
|
-
* @param probe - The `{ online, status?, error? }` a probe returned. An `online`
|
|
313
|
-
* probe is not a failure and yields `null`.
|
|
314
|
-
*/
|
|
315
|
-
declare function classifyProbeFailure(probe: {
|
|
316
|
-
online: boolean;
|
|
317
|
-
status?: number;
|
|
318
|
-
error?: string;
|
|
319
|
-
}): ProbeFailure | null;
|
|
320
|
-
/** A file as a compute response carries it; {@link extractFilesFromComputeResponse} decodes it. */
|
|
321
|
-
type FileData = {
|
|
322
|
-
/** Base filename without extension (e.g., "model") */
|
|
323
|
-
fileName: string;
|
|
324
|
-
/** File content, base64-encoded or plain string depending on isBase64Encoded flag */
|
|
325
|
-
data: string;
|
|
326
|
-
/** File extension including the dot (e.g., ".3dm", ".json"). Appended to fileName to create the full filename */
|
|
327
|
-
fileType: string;
|
|
328
|
-
/** Whether data is base64-encoded. If true, must be decoded to binary before use */
|
|
329
|
-
isBase64Encoded: boolean;
|
|
330
|
-
/** Directory path for archive organization (e.g., "subfolder/nested"). Empty string for root-level files */
|
|
331
|
-
subFolder: string;
|
|
332
|
-
/** Arbitrary metadata attached in Grasshopper. Not interpreted by compute; passed through for downstream consumers. May be absent on older payloads */
|
|
333
|
-
metadata?: Record<string, string>;
|
|
334
|
-
};
|
|
335
|
-
/** A decoded or fetched file, ready to archive or hand to a caller. */
|
|
336
|
-
type ProcessedFile = {
|
|
337
|
-
/** Full filename including extension (e.g., "model.3dm") */
|
|
338
|
-
fileName: string;
|
|
339
|
-
/** File content as binary data (Uint8Array for decoded base64 or fetched binary) or text */
|
|
340
|
-
content: Uint8Array | string;
|
|
341
|
-
/** File path for archive organization (e.g., "subfolder/model.3dm") */
|
|
342
|
-
path: string;
|
|
343
|
-
/**
|
|
344
|
-
* The sanitized `subFolder`, kept apart from `path` because re-splitting a renamed duplicate
|
|
345
|
-
* path is ambiguous. `''` is the archive root; absent on a hand-built `ProcessedFile`.
|
|
346
|
-
*/
|
|
347
|
-
subFolder?: string;
|
|
348
|
-
/** Carried through from {@link FileData}; absent when it had none, and on fetched files. */
|
|
349
|
-
metadata?: Record<string, string>;
|
|
350
|
-
};
|
|
351
|
-
/** An external file to fetch over HTTP and package alongside the response's own files. */
|
|
352
|
-
type FileBaseInfo = {
|
|
353
|
-
/** Destination filename for the file in the archive or result set (e.g., "additional-data.json") */
|
|
354
|
-
fileName: string;
|
|
355
|
-
/** URL to fetch the file from. Must be accessible from the runtime environment */
|
|
356
|
-
filePath: string;
|
|
357
|
-
/** Optional directory path for archive organization (e.g., "extras/docs"). When omitted, file lands at archive root */
|
|
358
|
-
subFolder?: string;
|
|
359
|
-
};
|
|
360
|
-
type DownloadOptions = {
|
|
361
|
-
/**
|
|
362
|
-
* Saves each finished archive instead of the default `<a download>` click. For hosts where an
|
|
363
|
-
* anchor download doesn't work, such as an embedded WebView that hands saves to native code.
|
|
364
|
-
* Awaited when it returns a promise, so archives still save one at a time.
|
|
365
|
-
*/
|
|
366
|
-
saveBlob?: (blob: Blob, fileName: string) => unknown;
|
|
367
|
-
};
|
|
368
|
-
/**
|
|
369
|
-
* Decode the files in a compute response, plus any external `additionalFiles`, without
|
|
370
|
-
* downloading them. Never throws: an unnamed or undecodable item and a failed external fetch are
|
|
371
|
-
* logged and dropped, the rest still resolve. Colliding archive paths are renamed
|
|
372
|
-
* (`model.txt` → `model-2.txt`), so a consumer keying by `path` loses nothing.
|
|
373
|
-
*/
|
|
374
|
-
declare const extractFilesFromComputeResponse: (downloadableFiles: FileData[], additionalFiles?: FileBaseInfo[] | FileBaseInfo | null) => Promise<ProcessedFile[]>;
|
|
375
|
-
/** Downloads files from a compute response as a ZIP archive. */
|
|
376
|
-
declare const downloadFileData: (downloadableFiles: FileData[], fileFoldername: string, additionalFiles?: FileBaseInfo[] | FileBaseInfo | null, options?: DownloadOptions) => Promise<void>;
|
|
377
|
-
/**
|
|
378
|
-
* Download one archive per `Sub Folder` root (see {@link groupFilesByRoot}). Files with no root go
|
|
379
|
-
* into `fallbackName`, so a definition that never sets `Sub Folder` downloads as one archive.
|
|
380
|
-
*
|
|
381
|
-
* Archives are saved one at a time: browsers discard concurrent downloads issued in the same tick.
|
|
382
|
-
* More than one save per gesture may prompt the user for permission.
|
|
383
|
-
*
|
|
384
|
-
* @param downloadableFiles - `FileData` items from the compute response.
|
|
385
|
-
* @param fallbackName - Archive name for files with no `Sub Folder` root.
|
|
386
|
-
* @param additionalFiles - Extra files to package; they carry no root and join the fallback archive.
|
|
387
|
-
* @param options - `saveBlob` replaces the anchor download for every archive.
|
|
388
|
-
*/
|
|
389
|
-
declare const downloadFileDataByRoot: (downloadableFiles: FileData[], fallbackName: string, additionalFiles?: FileBaseInfo[] | FileBaseInfo | null, options?: DownloadOptions) => Promise<void>;
|
|
390
|
-
/**
|
|
391
|
-
* The `Sub Folder` convention, as authored on Selva's Grasshopper file components.
|
|
392
|
-
*
|
|
393
|
-
* `::` nests, matching Rhino's layer separator (`ROOT::Panels`), and `/` and `\` are accepted
|
|
394
|
-
* because people type them out of habit. The plugin normalizes to `/` before sending, so these
|
|
395
|
-
* helpers also cover payloads from an older plugin that still emit `::`.
|
|
396
|
-
*
|
|
397
|
-
* The first segment is the **root**, which names the archive rather than becoming a folder inside
|
|
398
|
-
* it: `ROOT::Panels` downloads as `ROOT.zip` containing `Panels/…`. Files sharing a root travel
|
|
399
|
-
* together; distinct roots produce separate archives.
|
|
400
|
-
*/
|
|
401
|
-
/**
|
|
402
|
-
* Split a `Sub Folder` value into folder segments; `/`, `\` and `::` all separate.
|
|
403
|
-
*
|
|
404
|
-
* Exported because anything rendering a folder tree has to agree with the archive on where the
|
|
405
|
-
* boundaries are — splitting on `/` alone leaves `Main::Panels` as one literal segment and shows
|
|
406
|
-
* a folder named after the separator.
|
|
407
|
-
*/
|
|
408
|
-
declare const subFolderSegments: (subFolder: string | undefined) => string[];
|
|
409
|
-
/**
|
|
410
|
-
* Group files by their `Sub Folder` root, preserving encounter order.
|
|
411
|
-
*
|
|
412
|
-
* Rootless files group under `''` — a caller naming archives supplies its own fallback for that
|
|
413
|
-
* bucket. Useful beyond downloading: a consumer writing to disk gets the same grouping without
|
|
414
|
-
* touching the DOM.
|
|
415
|
-
*/
|
|
416
|
-
declare const groupFilesByRoot: <T extends Pick<FileData, "subFolder">>(files: readonly T[]) => Array<{
|
|
417
|
-
root: string;
|
|
418
|
-
files: T[];
|
|
419
|
-
}>;
|
|
420
|
-
export { ServerErrorCodeMap as A, enableDebugLogging as C, ComputeAuth as D, fetchCompute as E, ComputeError as M, ErrorCode as N, ComputeConfig as O, ErrorCodes as P, Logger as S, setLogger as T, SolveDefinition as _, extractFilesFromComputeResponse as a, hasField as b, FileData as c, ProbeVerdict as d, classifyProbeFailure as f, DefinitionRef as g, validateServerUrl as h, downloadFileDataByRoot as i, ServerTiming as j, RetryPolicy as k, ProcessedFile as l, ValidateServerUrlOptions as m, subFolderSegments as n, DownloadOptions as o, DEFAULT_BLOCKED_HOST as p, downloadFileData as r, FileBaseInfo as s, groupFilesByRoot as t, ProbeFailure as u, isDefinitionRef as v, getLogger as w, readField as x, decodeBase64ToBinary as y };
|
|
421
|
-
//# sourceMappingURL=index-DDmprCht.d.ts.map
|