@giveitsmaller/sdk 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_audit.js +5 -0
- package/dist/builder.d.ts +1 -8
- package/dist/builder.js +7 -5
- package/dist/errors.d.ts +16 -0
- package/dist/errors.js +22 -0
- package/dist/file-first.d.ts +223 -4
- package/dist/file-first.js +464 -69
- package/dist/gisl.d.ts +22 -1
- package/dist/gisl.js +31 -1
- package/dist/handle.d.ts +153 -0
- package/dist/handle.js +253 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +17 -1
- package/dist/merge.d.ts +2 -1
- package/dist/merge.js +43 -11
- package/package.json +1 -1
package/dist/_audit.js
CHANGED
|
@@ -129,7 +129,12 @@ export function _runAudit() {
|
|
|
129
129
|
accept();
|
|
130
130
|
accept();
|
|
131
131
|
accept();
|
|
132
|
+
// FF3a / u0hBt6fl — homogeneous fan-out builder surface.
|
|
132
133
|
accept();
|
|
133
134
|
accept();
|
|
134
135
|
accept();
|
|
136
|
+
accept();
|
|
137
|
+
// FF5a / Ao8RPVxD — file-first Handle reattach surface.
|
|
138
|
+
accept();
|
|
139
|
+
accept();
|
|
135
140
|
}
|
package/dist/builder.d.ts
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import type { GislClient } from './client.js';
|
|
28
28
|
import type { OperationDownload, WorkflowStatusResponse, SseOperationProgressDataStatusEnum } from '@giveitsmaller/contracts/openapi';
|
|
29
|
+
import { Handle } from './handle.js';
|
|
29
30
|
import type { PresetDefaults, PresetMedia } from './ergonomic/presets/index.js';
|
|
30
31
|
/**
|
|
31
32
|
* Best-effort detection of the compress-operation media from the
|
|
@@ -183,14 +184,6 @@ export interface Result {
|
|
|
183
184
|
*/
|
|
184
185
|
readonly resolvedOptions: ResolvedOptions;
|
|
185
186
|
}
|
|
186
|
-
/**
|
|
187
|
-
* Lighter return value from `.submit({webhook})` — no SSE/poll wait,
|
|
188
|
-
* caller reconciles completion via the webhook.
|
|
189
|
-
*/
|
|
190
|
-
export interface Handle {
|
|
191
|
-
readonly workflowId: string;
|
|
192
|
-
readonly webhookSecret?: string;
|
|
193
|
-
}
|
|
194
187
|
/**
|
|
195
188
|
* Upload-phase progress event. The byte counter comes from
|
|
196
189
|
* `UploadOptions.onProgress` — there is no `phase` field on the wire.
|
package/dist/builder.js
CHANGED
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
import { SseEventType, SseOperationProgressDataFromJSON, } from '@giveitsmaller/contracts/openapi';
|
|
28
28
|
import { uploadSource } from './types.js';
|
|
29
29
|
import { GislTimeoutError } from './errors.js';
|
|
30
|
+
// Deferred-usage-only import: `Handle` is constructed inside submit() at call
|
|
31
|
+
// time, not at module load, so the builder.ts <-> handle.ts cycle is safe
|
|
32
|
+
// under ESM (handle.ts imports the await-primitives from this module).
|
|
33
|
+
import { Handle } from './handle.js';
|
|
30
34
|
import { resolveCompressOptions, } from './ergonomic/preset_resolver.js';
|
|
31
35
|
/**
|
|
32
36
|
* Best-effort detection of the compress-operation media from the
|
|
@@ -264,11 +268,9 @@ export class OperationBuilder {
|
|
|
264
268
|
callback_url: options.webhook,
|
|
265
269
|
};
|
|
266
270
|
const created = await this.client.createWorkflow(payload);
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
};
|
|
271
|
-
return handle;
|
|
271
|
+
// No client passed → the returned Handle's status()/wait()/result()
|
|
272
|
+
// throw `no_client`; the operation-first submit reconciles via webhook.
|
|
273
|
+
return new Handle(created.workflowId, created.webhookSecret != null ? created.webhookSecret : undefined);
|
|
272
274
|
}
|
|
273
275
|
/**
|
|
274
276
|
* Fan-out chain: run this builder to completion, then for each artifact
|
package/dist/errors.d.ts
CHANGED
|
@@ -348,6 +348,22 @@ export declare class GislMultipartPartCountError extends GislError {
|
|
|
348
348
|
export declare class GislNoSuchKeyError extends GislError {
|
|
349
349
|
constructor(message: string);
|
|
350
350
|
}
|
|
351
|
+
/**
|
|
352
|
+
* Thrown by the file-first `Handle.result()` (FF5a) when the workflow has not
|
|
353
|
+
* yet reached a terminal state. `result()` is the NON-blocking accessor: it
|
|
354
|
+
* fetches the current status once and, if the workflow is still
|
|
355
|
+
* `pending`/`in_progress`, throws this rather than waiting. Use `Handle.wait()`
|
|
356
|
+
* to block until terminal instead.
|
|
357
|
+
*
|
|
358
|
+
* Carries the `workflowId` and the current (non-terminal) `state`.
|
|
359
|
+
*
|
|
360
|
+
* Mirrors the PHP `Gisl\Sdk\Errors\GislResultNotReadyError`.
|
|
361
|
+
*/
|
|
362
|
+
export declare class GislResultNotReadyError extends GislError {
|
|
363
|
+
readonly workflowId: string;
|
|
364
|
+
readonly state: string;
|
|
365
|
+
constructor(workflowId: string, state: string);
|
|
366
|
+
}
|
|
351
367
|
/** Machine-readable cause carried by {@link GislSinkError}. */
|
|
352
368
|
export type GislSinkErrorReason = 'not_single_output' | 'downloader_unavailable' | 'partial_failure' | 'duplicate_filename' | 'invalid_directory' | 'write_failed';
|
|
353
369
|
/**
|
package/dist/errors.js
CHANGED
|
@@ -387,6 +387,28 @@ export class GislNoSuchKeyError extends GislError {
|
|
|
387
387
|
this.name = 'GislNoSuchKeyError';
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* Thrown by the file-first `Handle.result()` (FF5a) when the workflow has not
|
|
392
|
+
* yet reached a terminal state. `result()` is the NON-blocking accessor: it
|
|
393
|
+
* fetches the current status once and, if the workflow is still
|
|
394
|
+
* `pending`/`in_progress`, throws this rather than waiting. Use `Handle.wait()`
|
|
395
|
+
* to block until terminal instead.
|
|
396
|
+
*
|
|
397
|
+
* Carries the `workflowId` and the current (non-terminal) `state`.
|
|
398
|
+
*
|
|
399
|
+
* Mirrors the PHP `Gisl\Sdk\Errors\GislResultNotReadyError`.
|
|
400
|
+
*/
|
|
401
|
+
export class GislResultNotReadyError extends GislError {
|
|
402
|
+
workflowId;
|
|
403
|
+
state;
|
|
404
|
+
constructor(workflowId, state) {
|
|
405
|
+
super(`Workflow ${workflowId} is not ready (state '${state}'); its result is not available yet. ` +
|
|
406
|
+
'Call wait() to block until it reaches a terminal state, or poll result() again later.');
|
|
407
|
+
this.name = 'GislResultNotReadyError';
|
|
408
|
+
this.workflowId = workflowId;
|
|
409
|
+
this.state = state;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
390
412
|
/**
|
|
391
413
|
* Thrown by the file-first `RunResult` sinks (`toFile()` / `downloadTo()`,
|
|
392
414
|
* FF1) when they cannot deliver. The machine-readable `reason` discriminates
|
package/dist/file-first.d.ts
CHANGED
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { type ProgressEvent } from './builder.js';
|
|
13
13
|
import type { GislClient } from './client.js';
|
|
14
|
+
import type { OperationDownload, WorkflowStatusResponse } from '@giveitsmaller/contracts/openapi';
|
|
14
15
|
import { OptimizeFor } from './generated/sdk_spec/enums.js';
|
|
15
16
|
import type { PresetDefaults } from './ergonomic/presets/index.js';
|
|
16
17
|
import type { WorkflowCreatePayload } from './types.js';
|
|
18
|
+
import { Handle } from './handle.js';
|
|
17
19
|
/**
|
|
18
20
|
* Streams a single output URL to a local path. The seam between the
|
|
19
21
|
* file-first {@link RunResult} sinks and the SDK's HTTP/auth layer.
|
|
@@ -160,6 +162,68 @@ export declare class RunResult {
|
|
|
160
162
|
};
|
|
161
163
|
private requireDownloader;
|
|
162
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Flatten the terminal workflow status + its downloads into a {@link RunResult}.
|
|
167
|
+
*
|
|
168
|
+
* Shared by {@link Recipe.run} (passes its recipe key) and the file-first
|
|
169
|
+
* {@link Handle} reattach surface (`Handle.wait()`/`Handle.result()`, FF5a —
|
|
170
|
+
* passes `null` because a reattached handle carries no recipe key).
|
|
171
|
+
*
|
|
172
|
+
* **Partition invariant (carries a prior codex-review fix — do NOT let it
|
|
173
|
+
* drift):** success is ONLY `state === 'completed'`. Every other terminal
|
|
174
|
+
* state — `failed`, `partially_failed`, `cancelled`, `expired`,
|
|
175
|
+
* `paused_insufficient_credits` — partitions into `failed[]` so a caller's
|
|
176
|
+
* `ok`/`succeeded` check can never treat a cancelled/expired/paused run as a
|
|
177
|
+
* clean result.
|
|
178
|
+
*
|
|
179
|
+
* @internal Exported for reuse by the file-first `Handle`; not part of the
|
|
180
|
+
* caller-facing fluent surface.
|
|
181
|
+
*/
|
|
182
|
+
export declare function projectDownloadsToRunResult(workflowId: string, finalStatus: WorkflowStatusResponse, jobDownloads: readonly {
|
|
183
|
+
files: readonly OperationDownload[];
|
|
184
|
+
}[], key: string | null, downloader?: Downloader): RunResult;
|
|
185
|
+
/**
|
|
186
|
+
* Flatten a terminal multi-job workflow (the `client.files([...])` fan-out)
|
|
187
|
+
* into a partitioned {@link RunResult}. One job per input file, keyed by the
|
|
188
|
+
* `file-{i}` job ref the {@link FilesRecipe} lowering assigns; the result's
|
|
189
|
+
* `succeeded` / `failed` partition is PER JOB, so one bad input does not sink
|
|
190
|
+
* the rest.
|
|
191
|
+
*
|
|
192
|
+
* Join model: `finalStatus.jobs[]` carries the per-job {@link JobStatus} +
|
|
193
|
+
* `operations[]` (for the error message); `jobDownloads[]` carries the per-job
|
|
194
|
+
* output files. Both are joined on the job `ref` ("file-{i}"); the partition
|
|
195
|
+
* key is the index `"{i}"` parsed out of that ref. The flat `artifacts[]` is
|
|
196
|
+
* every job's outputs in job order (the order `finalStatus.jobs[]` lists them).
|
|
197
|
+
*
|
|
198
|
+
* **Partition invariant (mirrors {@link projectDownloadsToRunResult} PER JOB —
|
|
199
|
+
* do NOT let it drift):** a job is a SUCCESS only when its
|
|
200
|
+
* {@link JobResponse.status} `=== 'completed'`. Any other per-job status —
|
|
201
|
+
* `failed`, `pending`, `waiting`, `blocked_insufficient_credits`,
|
|
202
|
+
* `in_progress` — partitions that job into `failed[]` (with that job's first
|
|
203
|
+
* operation error message, scoped to THAT job only).
|
|
204
|
+
*
|
|
205
|
+
* @internal Exported for the file-first `client.files([...]).run()` producer;
|
|
206
|
+
* not part of the caller-facing fluent surface.
|
|
207
|
+
*/
|
|
208
|
+
export declare function projectMultiJobToRunResult(workflowId: string, finalStatus: WorkflowStatusResponse, jobDownloads: readonly {
|
|
209
|
+
ref: string;
|
|
210
|
+
files: readonly OperationDownload[];
|
|
211
|
+
}[], keyByRef: ReadonlyMap<string, string | null>, downloader?: Downloader): RunResult;
|
|
212
|
+
/**
|
|
213
|
+
* True when a terminal status describes a homogeneous `files([...])` fan-out —
|
|
214
|
+
* i.e. it has at least one job and EVERY job ref is `file-{i}` (the ids the
|
|
215
|
+
* {@link FilesRecipe} lowering assigns). A single-file {@link Recipe} omits the
|
|
216
|
+
* job id, so its job carries a non-`file-N` ref (e.g. `op`) and this is false.
|
|
217
|
+
*
|
|
218
|
+
* This is the data-driven seam that lets {@link Handle.wait}/{@link Handle.result}
|
|
219
|
+
* pick the per-job producer ({@link projectMultiJobToRunResult}) over the
|
|
220
|
+
* single-output one for a fan-out — WITHOUT a construction-time marker, so a
|
|
221
|
+
* fan-out **reattached** via `client.workflow(id)` (which carries no marker)
|
|
222
|
+
* still partitions per job. Keys are recovered from the `file-{i}` refs.
|
|
223
|
+
*
|
|
224
|
+
* @internal Exported for the file-first `Handle`; not part of the public API.
|
|
225
|
+
*/
|
|
226
|
+
export declare function isFanoutStatus(finalStatus: WorkflowStatusResponse): boolean;
|
|
163
227
|
/**
|
|
164
228
|
* The primary file a {@link Recipe} operates on — the "subject" of the
|
|
165
229
|
* file-first surface. A discriminated union over the ways a caller names an
|
|
@@ -250,15 +314,25 @@ export declare class Recipe {
|
|
|
250
314
|
* `operations[]`; the job `id` is omitted (a single job referenced by
|
|
251
315
|
* nothing — the server auto-assigns `job_N`).
|
|
252
316
|
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
317
|
+
* When `callbackUrl` is given (the file-first `submit()` path), it is built
|
|
318
|
+
* INTO the payload at construction (`callback_url`) rather than spread onto an
|
|
319
|
+
* already-built readonly payload. `run()` passes no `callbackUrl`.
|
|
320
|
+
*
|
|
321
|
+
* @internal Consumed by FF2b's `run()` (after a real upload), FF5b's
|
|
322
|
+
* `submit()` (with a webhook), and the cross-language parity harness (with a
|
|
323
|
+
* fixed id). Not part of the caller-facing fluent surface.
|
|
256
324
|
*/
|
|
257
|
-
toWorkflowPayload(fileId: string): WorkflowCreatePayload;
|
|
325
|
+
toWorkflowPayload(fileId: string, callbackUrl?: string): WorkflowCreatePayload;
|
|
258
326
|
/** The result-addressing key passed to `file()`, or undefined. */
|
|
259
327
|
key(): string | undefined;
|
|
260
328
|
/** The number of operations chained so far (introspection / tests). */
|
|
261
329
|
get stepCount(): number;
|
|
330
|
+
/**
|
|
331
|
+
* The captured op chain. Read by {@link FilesRecipe} to compose a shared
|
|
332
|
+
* chain across many inputs without duplicating the chain-method validation.
|
|
333
|
+
* @internal
|
|
334
|
+
*/
|
|
335
|
+
get recipeSteps(): readonly RecipeStep[];
|
|
262
336
|
/**
|
|
263
337
|
* Execute the recipe end-to-end: upload the input (when required), create
|
|
264
338
|
* the workflow, await a terminal state (SSE with poll fallback), then
|
|
@@ -276,9 +350,154 @@ export declare class Recipe {
|
|
|
276
350
|
signal?: AbortSignal;
|
|
277
351
|
pollIntervalMs?: number;
|
|
278
352
|
}): Promise<RunResult>;
|
|
353
|
+
/**
|
|
354
|
+
* Fire-and-forget the recipe: upload the input (when required), create the
|
|
355
|
+
* workflow (wiring `webhook` into `callback_url` when given), and return a
|
|
356
|
+
* client-bound {@link Handle} carrying the workflow id + webhook secret + the
|
|
357
|
+
* recipe key. Does NOT wait for terminal status — call `handle.wait()` /
|
|
358
|
+
* `handle.result()` later to collect the {@link RunResult}.
|
|
359
|
+
*
|
|
360
|
+
* Requires a client bound at construction time (same `no_client` guard as
|
|
361
|
+
* {@link run}). `webhook` is OPTIONAL: when omitted, no `callback_url` is
|
|
362
|
+
* sent. Mirrors the PHP `Recipe.submit()`.
|
|
363
|
+
*
|
|
364
|
+
* @param webhook Absolute callback URL the server POSTs lifecycle events to.
|
|
365
|
+
*/
|
|
366
|
+
submit(webhook?: string): Promise<Handle>;
|
|
367
|
+
/**
|
|
368
|
+
* Resolve the upload id (verbatim for a pre-uploaded id; uploading a path /
|
|
369
|
+
* blob otherwise, emitting `{phase:'upload'}` progress), check the post-upload
|
|
370
|
+
* deadline, lower to the workflow-create payload (wiring `webhook` into
|
|
371
|
+
* `callback_url`), and create the workflow. Shared first half of
|
|
372
|
+
* {@link run} + {@link submit}.
|
|
373
|
+
*
|
|
374
|
+
* The post-upload deadline check carries a prior codex fix (9a117f04eb59): a
|
|
375
|
+
* slow upload must not proceed to createWorkflow past the deadline.
|
|
376
|
+
*/
|
|
377
|
+
private _uploadAndCreate;
|
|
279
378
|
private withStep;
|
|
280
379
|
private lowerStep;
|
|
281
380
|
private lowerCompressOptions;
|
|
282
381
|
private compressMediaHint;
|
|
283
382
|
}
|
|
383
|
+
/**
|
|
384
|
+
* The homogeneous fan-out builder value (FF3a). `client.files([a, b, c])`
|
|
385
|
+
* returns a `FilesRecipe`; the op-chain methods (`compress`, `convert`,
|
|
386
|
+
* `thumbnail`, `textWatermark`) build ONE shared recipe (chain) that is applied
|
|
387
|
+
* to EVERY input file in ONE workflow. `run()` returns a partitioned
|
|
388
|
+
* {@link RunResult} — one `succeeded`/`failed` entry per input, keyed by its
|
|
389
|
+
* 0-based index ("0", "1", …) so one bad input does not sink the rest.
|
|
390
|
+
*
|
|
391
|
+
* **Immutable / clone-on-write**, exactly like {@link Recipe}: every op returns
|
|
392
|
+
* a NEW `FilesRecipe` carrying the appended step. The inputs are held as an
|
|
393
|
+
* ORDERED list (NOT a map) so the per-file index is the partition key.
|
|
394
|
+
*
|
|
395
|
+
* **Lowering composes {@link Recipe} per file** rather than duplicating
|
|
396
|
+
* `lowerStep`/`lowerCompressOptions`: for each input `i` it builds an internal
|
|
397
|
+
* single-file `Recipe(input_i, …, steps)`, calls its `toWorkflowPayload` to get
|
|
398
|
+
* that file's one-job payload, then merges all jobs into ONE
|
|
399
|
+
* {@link WorkflowCreatePayload} with `jobs[i].id = "file-{i}"`. This preserves
|
|
400
|
+
* each file's media-hint (different extensions per input resolve compress
|
|
401
|
+
* presets independently).
|
|
402
|
+
*
|
|
403
|
+
* Exposes both `run()` (blocking, returns a partitioned {@link RunResult}) and
|
|
404
|
+
* `submit(webhook?)` (fire-and-forget, returns a {@link Handle}). Mirrors the
|
|
405
|
+
* PHP `FilesRecipe`.
|
|
406
|
+
*/
|
|
407
|
+
export declare class FilesRecipe {
|
|
408
|
+
private readonly inputs;
|
|
409
|
+
private readonly steps;
|
|
410
|
+
private readonly presetDefaults?;
|
|
411
|
+
private readonly scopedPresetDefaults?;
|
|
412
|
+
private readonly client?;
|
|
413
|
+
constructor(inputs: readonly FileInput[], steps?: readonly RecipeStep[], presetDefaults?: PresetDefaults | undefined, scopedPresetDefaults?: PresetDefaults | undefined, client?: GislClient | undefined);
|
|
414
|
+
/**
|
|
415
|
+
* Reduce file size on every input. `optimize` selects a per-media preset
|
|
416
|
+
* (resolved per file at lower-time, so each input's extension picks its own
|
|
417
|
+
* preset). Reuses {@link Recipe}'s validation — a directly-constructed
|
|
418
|
+
* lowering builds an internal Recipe that throws the same `GislConfigError`.
|
|
419
|
+
*/
|
|
420
|
+
compress(optimize?: OptimizeFor): FilesRecipe;
|
|
421
|
+
/** Change every input's format. `format` lowers verbatim to the `format` option. */
|
|
422
|
+
convert(format: string): FilesRecipe;
|
|
423
|
+
/** Generate a preview of every input. Omitted dimensions are dropped from the wire options. */
|
|
424
|
+
thumbnail(options?: {
|
|
425
|
+
width?: number;
|
|
426
|
+
height?: number;
|
|
427
|
+
}): FilesRecipe;
|
|
428
|
+
/** Apply the same text watermark to every input. */
|
|
429
|
+
textWatermark(text: string): FilesRecipe;
|
|
430
|
+
/** The number of inputs in this fan-out (introspection / tests). */
|
|
431
|
+
get inputCount(): number;
|
|
432
|
+
/** The number of operations chained so far (introspection / tests). */
|
|
433
|
+
get stepCount(): number;
|
|
434
|
+
/**
|
|
435
|
+
* Lower this fan-out to a single multi-job workflow-create payload against a
|
|
436
|
+
* list of resolved upload ids (one per input, in input order). Each input `i`
|
|
437
|
+
* becomes ONE job with `id = "file-{i}"`, its `source: upload(fileIds[i])`,
|
|
438
|
+
* and the SHARED lowered `operations[]`. Composes the single-file
|
|
439
|
+
* {@link Recipe.toWorkflowPayload} per file so per-file media-hints resolve
|
|
440
|
+
* independently and lowering logic is not duplicated.
|
|
441
|
+
*
|
|
442
|
+
* @internal Consumed by {@link run} (after uploading all inputs) and the
|
|
443
|
+
* cross-language parity harness (with fixed ids). Not caller-facing.
|
|
444
|
+
*/
|
|
445
|
+
toWorkflowPayload(fileIds: readonly string[], callbackUrl?: string): WorkflowCreatePayload;
|
|
446
|
+
/**
|
|
447
|
+
* Execute the fan-out end-to-end: upload EVERY input, create ONE workflow
|
|
448
|
+
* with one job per input, await a terminal state (SSE with poll fallback),
|
|
449
|
+
* then resolve the per-job downloads into a partitioned {@link RunResult}.
|
|
450
|
+
* `partially_failed` is a NORMAL terminal state here — its successful jobs
|
|
451
|
+
* land in `succeeded`, its failed jobs in `failed`.
|
|
452
|
+
*
|
|
453
|
+
* Requires a client bound at construction time — `gisl().files(...)` wires
|
|
454
|
+
* it; a directly-constructed `FilesRecipe` throws {@link GislConfigError}.
|
|
455
|
+
* Mirrors the single-file {@link Recipe.run}; see {@link submit} for the
|
|
456
|
+
* fire-and-forget arm.
|
|
457
|
+
*/
|
|
458
|
+
run(options?: {
|
|
459
|
+
maxWait?: string | number;
|
|
460
|
+
onProgress?: (event: ProgressEvent) => void;
|
|
461
|
+
signal?: AbortSignal;
|
|
462
|
+
pollIntervalMs?: number;
|
|
463
|
+
}): Promise<RunResult>;
|
|
464
|
+
/**
|
|
465
|
+
* Fire-and-forget the fan-out: upload every input, create ONE multi-job
|
|
466
|
+
* workflow (wiring `webhook` into `callback_url` when given), and return a
|
|
467
|
+
* client-bound {@link Handle}. Does NOT wait for terminal status — call
|
|
468
|
+
* `handle.wait()` / `handle.result()` later to collect the partitioned
|
|
469
|
+
* {@link RunResult}. The Handle detects the fan-out from the wire `file-{i}`
|
|
470
|
+
* job refs, so per-file `byKey()` works even after a `client.workflow(id)`
|
|
471
|
+
* reattach (the keys are the input indices `"0"`, `"1"`, …).
|
|
472
|
+
*
|
|
473
|
+
* Requires a client bound at construction time (same `no_client` guard as
|
|
474
|
+
* {@link run}). `webhook` is OPTIONAL. Fire-and-forget, so NO whole-run
|
|
475
|
+
* deadline (a multi-GB upload is bounded by the HTTP client's own timeout).
|
|
476
|
+
* Mirrors the single-file {@link Recipe.submit}.
|
|
477
|
+
*
|
|
478
|
+
* @param webhook Absolute callback URL the server POSTs lifecycle events to.
|
|
479
|
+
*/
|
|
480
|
+
submit(webhook?: string): Promise<Handle>;
|
|
481
|
+
/**
|
|
482
|
+
* Upload every input (verbatim for a pre-uploaded id; uploading a path /
|
|
483
|
+
* blob otherwise, emitting `{phase:'upload'}` progress) then create ONE
|
|
484
|
+
* multi-job workflow (one job per input, `callback_url` built in when
|
|
485
|
+
* `webhook` is given). Shared first half of {@link run} + {@link submit}.
|
|
486
|
+
*
|
|
487
|
+
* Uploads are sequential so progress events stay ordered and the abort
|
|
488
|
+
* signal is honoured promptly; a resource arm is impossible in TS (Blob).
|
|
489
|
+
* `run()` passes a whole-run deadline (a slow upload must not proceed to
|
|
490
|
+
* createWorkflow past maxWait); `submit()` passes `undefined`, so the
|
|
491
|
+
* deadline checks are skipped.
|
|
492
|
+
*/
|
|
493
|
+
private _uploadAllAndCreate;
|
|
494
|
+
/**
|
|
495
|
+
* The shared single-file {@link Recipe} that captures the op chain (input is
|
|
496
|
+
* a placeholder — only the steps are read). Reuses Recipe's op-chain
|
|
497
|
+
* validation + coercion so a `FilesRecipe.compress(bad)` throws the identical
|
|
498
|
+
* `GislConfigError` as `Recipe.compress(bad)`.
|
|
499
|
+
*/
|
|
500
|
+
private baseRecipe;
|
|
501
|
+
private withStep;
|
|
502
|
+
}
|
|
284
503
|
export {};
|