@oeave/bakery3 0.0.0-stage → 0.2.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.
Files changed (86) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +562 -2
  3. package/dist/animation-B1h0Ryvj.d.ts +97 -0
  4. package/dist/bake/index.d.ts +369 -0
  5. package/dist/bake/index.js +9 -0
  6. package/dist/bake/index.js.map +1 -0
  7. package/dist/bake-DZ-CJR6f.d.ts +1364 -0
  8. package/dist/catalog/index.d.ts +100 -0
  9. package/dist/catalog/index.js +154 -0
  10. package/dist/catalog/index.js.map +1 -0
  11. package/dist/catalog.gen-BM-aNf7n.d.ts +733 -0
  12. package/dist/chunk-3G5QL4F4.js +145 -0
  13. package/dist/chunk-3G5QL4F4.js.map +1 -0
  14. package/dist/chunk-4E5VV4QY.js +12 -0
  15. package/dist/chunk-4E5VV4QY.js.map +1 -0
  16. package/dist/chunk-62M6XXNX.js +142 -0
  17. package/dist/chunk-62M6XXNX.js.map +1 -0
  18. package/dist/chunk-6FYI6AJM.js +1157 -0
  19. package/dist/chunk-6FYI6AJM.js.map +1 -0
  20. package/dist/chunk-6NYR73Y7.js +832 -0
  21. package/dist/chunk-6NYR73Y7.js.map +1 -0
  22. package/dist/chunk-APWUCEEB.js +118 -0
  23. package/dist/chunk-APWUCEEB.js.map +1 -0
  24. package/dist/chunk-HNMSWQU7.js +1709 -0
  25. package/dist/chunk-HNMSWQU7.js.map +1 -0
  26. package/dist/chunk-JFYUDERE.js +1412 -0
  27. package/dist/chunk-JFYUDERE.js.map +1 -0
  28. package/dist/chunk-KNUAOILG.js +551 -0
  29. package/dist/chunk-KNUAOILG.js.map +1 -0
  30. package/dist/chunk-KZLVTSBI.js +191 -0
  31. package/dist/chunk-KZLVTSBI.js.map +1 -0
  32. package/dist/chunk-LAKXC4WR.js +2028 -0
  33. package/dist/chunk-LAKXC4WR.js.map +1 -0
  34. package/dist/chunk-NXBAZGNB.js +1107 -0
  35. package/dist/chunk-NXBAZGNB.js.map +1 -0
  36. package/dist/chunk-QRCT5UGZ.js +3286 -0
  37. package/dist/chunk-QRCT5UGZ.js.map +1 -0
  38. package/dist/chunk-S4AJTLLN.js +23 -0
  39. package/dist/chunk-S4AJTLLN.js.map +1 -0
  40. package/dist/chunk-UWBP7B54.js +92 -0
  41. package/dist/chunk-UWBP7B54.js.map +1 -0
  42. package/dist/chunk-XK35ANPJ.js +346 -0
  43. package/dist/chunk-XK35ANPJ.js.map +1 -0
  44. package/dist/chunk-Z7IYVH22.js +4781 -0
  45. package/dist/chunk-Z7IYVH22.js.map +1 -0
  46. package/dist/chunk-ZEBVAIJJ.js +156 -0
  47. package/dist/chunk-ZEBVAIJJ.js.map +1 -0
  48. package/dist/devtools/index.d.ts +536 -0
  49. package/dist/devtools/index.js +15 -0
  50. package/dist/devtools/index.js.map +1 -0
  51. package/dist/environments/index.d.ts +93 -0
  52. package/dist/environments/index.js +382 -0
  53. package/dist/environments/index.js.map +1 -0
  54. package/dist/hotspots/index.d.ts +111 -0
  55. package/dist/hotspots/index.js +285 -0
  56. package/dist/hotspots/index.js.map +1 -0
  57. package/dist/index.d.ts +975 -0
  58. package/dist/index.js +15 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/node/index.cjs +5240 -0
  61. package/dist/node/index.cjs.map +1 -0
  62. package/dist/node/index.d.cts +4927 -0
  63. package/dist/node/index.d.ts +597 -0
  64. package/dist/node/index.js +1328 -0
  65. package/dist/node/index.js.map +1 -0
  66. package/dist/prepare-BtjY4G3q.d.ts +112 -0
  67. package/dist/presets/index.d.ts +562 -0
  68. package/dist/presets/index.js +14 -0
  69. package/dist/presets/index.js.map +1 -0
  70. package/dist/r3f/index.d.ts +159 -0
  71. package/dist/r3f/index.js +592 -0
  72. package/dist/r3f/index.js.map +1 -0
  73. package/dist/room-FS26KAPQ.js +9 -0
  74. package/dist/room-FS26KAPQ.js.map +1 -0
  75. package/dist/rooms.gen-DItzBR9k.d.ts +1462 -0
  76. package/dist/session-VCIQEO26.js +9 -0
  77. package/dist/session-VCIQEO26.js.map +1 -0
  78. package/dist/shapes/index.d.ts +222 -0
  79. package/dist/shapes/index.js +836 -0
  80. package/dist/shapes/index.js.map +1 -0
  81. package/dist/testRun-20OARnQr.d.ts +1139 -0
  82. package/dist/timeline-ChwgD7bT.d.ts +470 -0
  83. package/dist/tsl/index.d.ts +165 -0
  84. package/dist/tsl/index.js +310 -0
  85. package/dist/tsl/index.js.map +1 -0
  86. package/package.json +170 -4
@@ -0,0 +1,1139 @@
1
+ import { R as RenderSpec, e as BakeSpec, f as BakeBundleSummary, V as Vec3, g as CameraSpec, h as CompatibilityIssue, A as AssetHash, i as BakeSettings } from './bake-DZ-CJR6f.js';
2
+
3
+ /**
4
+ * A batch: a customer's declared body of work.
5
+ *
6
+ * A catalog is products x finishes x cameras, a few thousand stills. The
7
+ * customer opens a batch, adds items in pages, closes it, and reads one
8
+ * ledger back. On the control plane every item is a render row with a
9
+ * `batchId`, staged behind the queue proper and fed into it a page at a
10
+ * time, so everything that holds for a render (the claim, the reservation,
11
+ * single billing, webhooks, retention) holds for an item because it is one.
12
+ */
13
+
14
+ declare const BATCH_STATES: readonly ["open", "sealed", "paused", "completed", "cancelled"];
15
+ type BatchState = (typeof BATCH_STATES)[number];
16
+ /**
17
+ * How many items are in each state. `staged` items are admitted: priced,
18
+ * reserved, waiting behind the queue proper. `queued` are in the queue and
19
+ * `running` hold a worker. `refused` failed for a reason a retry would not
20
+ * change (the scene's fault, or ours to explain); `failed` ran out of
21
+ * attempts on an infrastructure failure. `adopted` were already completed
22
+ * under the same key when they were added and cost nothing.
23
+ */
24
+ type BatchCounts = {
25
+ staged: number;
26
+ queued: number;
27
+ running: number;
28
+ completed: number;
29
+ failed: number;
30
+ refused: number;
31
+ cancelled: number;
32
+ adopted: number;
33
+ };
34
+ type BatchCost = {
35
+ /** Sum of estimatedCost over admitted items. */
36
+ estimated: number;
37
+ /** Sum of maximumCost over admitted items: what admission reserved. */
38
+ maximum: number;
39
+ /** Sum of what completed items actually cost, so far. */
40
+ actual: number;
41
+ };
42
+ type BatchRecord = {
43
+ id: string;
44
+ key: string;
45
+ name?: string;
46
+ kind: 'render' | 'bake';
47
+ state: BatchState;
48
+ lane: 'batch' | 'normal';
49
+ maxParallel?: number;
50
+ /** The customer's ceiling for the whole batch. */
51
+ maxCost?: number;
52
+ counts: BatchCounts;
53
+ /** Every item ever admitted, adopted included. */
54
+ total: number;
55
+ /** How many are terminal. `done === total` once sealed is `completed`. */
56
+ done: number;
57
+ cost: BatchCost;
58
+ /** Why it is paused, when it is: the breaker names the top refusal codes. */
59
+ pausedReason?: string;
60
+ createdAt: number;
61
+ sealedAt?: number;
62
+ finishedAt?: number;
63
+ };
64
+ type BatchOpenRequest = {
65
+ /**
66
+ * Stable across re-runs: the same key re-opens the same batch while it is
67
+ * not terminal, and items already completed under their keys are adopted
68
+ * rather than rendered again.
69
+ */
70
+ key: string;
71
+ name?: string;
72
+ kind?: 'render' | 'bake';
73
+ /**
74
+ * The ceiling for the whole batch, in dollars. A page that would take the
75
+ * batch's maximum past it is refused whole.
76
+ */
77
+ maxCost?: number;
78
+ /**
79
+ * `batch` (the default) never runs ahead of a person in a configurator;
80
+ * `normal` is the API's ordinary lane.
81
+ */
82
+ lane?: 'batch' | 'normal';
83
+ /** Fewer parallel items than the plan allows, for a gentler budget. */
84
+ maxParallel?: number;
85
+ };
86
+ type BatchItemRequest = {
87
+ /**
88
+ * The item's idempotency key, scoped to the project like every other
89
+ * render's. `sku/finish/camera@v3` is the shape the docs suggest.
90
+ */
91
+ key: string;
92
+ spec: RenderSpec | BakeSpec;
93
+ metadata?: Record<string, unknown>;
94
+ /** A ceiling for this one item, under the batch's. */
95
+ maxCost?: number;
96
+ };
97
+ type BatchAddRequest = {
98
+ items: BatchItemRequest[];
99
+ /**
100
+ * Price everything, admit nothing: the whole catalog's numbers before a
101
+ * dollar is reserved.
102
+ */
103
+ dryRun?: boolean;
104
+ };
105
+ type BatchItemOutcome = {
106
+ key: string;
107
+ /** The render's id, when it was admitted or adopted. */
108
+ id?: string;
109
+ estimatedCost: number;
110
+ maximumCost: number;
111
+ /** Already completed under this key: attached at no cost. */
112
+ adopted?: boolean;
113
+ /**
114
+ * Why this item, alone, was not admitted (a bad spec, an item over its own
115
+ * maxCost). The page's other items are unaffected.
116
+ */
117
+ error?: RenderError;
118
+ };
119
+ type BatchAddResponse = {
120
+ batch: BatchRecord;
121
+ items: BatchItemOutcome[];
122
+ };
123
+ /** One line of `GET /v1/batches/:id/export`: the ledger, item by item. */
124
+ type BatchExportLine = {
125
+ key: string;
126
+ id: string;
127
+ state: string;
128
+ resultUrl?: string;
129
+ error?: RenderError;
130
+ cost?: number;
131
+ versions?: Record<string, unknown>;
132
+ metadata?: Record<string, unknown>;
133
+ };
134
+
135
+ /**
136
+ * Render job states and the events that carry them.
137
+ *
138
+ * Every transition is timestamped, idempotent and observable. Idempotent is
139
+ * the load-bearing word: a worker that retries a stage must not bill twice
140
+ * and must not emit `render.completed` twice, so the control plane treats a
141
+ * transition to a state it is already in as a no-op rather than an error.
142
+ */
143
+ declare const RENDER_STATES: readonly ["created", "uploading", "validating", "queued", "starting", "preparing", "rendering_preview", "rendering", "encoding", "uploading_result", "completed", "failed", "cancelled", "expired"];
144
+ type RenderState = (typeof RENDER_STATES)[number];
145
+ type RenderResult = {
146
+ /**
147
+ * Signed, private, and only good until `expiresAt` (24 hours). Copy the
148
+ * bytes into your own storage if you keep them; `getRender(id)` hands out
149
+ * fresh URLs until the project's retention deletes the files.
150
+ */
151
+ url: string;
152
+ /**
153
+ * Millisecond epoch at which `url` (and `previewUrl`) stop working. The
154
+ * URLs are signed when the render is read, so reading it again with
155
+ * `getRender(id)` returns fresh ones. Absent from an API that predates it.
156
+ */
157
+ expiresAt?: number;
158
+ width: number;
159
+ height: number;
160
+ format: string;
161
+ bytes: number;
162
+ /** What was actually charged, in USD. Not the estimate. */
163
+ cost: number;
164
+ /** Everything needed to reproduce this exact image later. */
165
+ versions: {
166
+ protocol: string;
167
+ sdk: string;
168
+ translator: string;
169
+ qualityPreset: string;
170
+ };
171
+ };
172
+ /**
173
+ * Which queue a render waits in inside its account.
174
+ *
175
+ * `interactive` is a person waiting: every browser-token render, and the
176
+ * SDK's `render()` by default. `normal` is the API default. `batch` is an
177
+ * item of a batch. A lane above always dispatches before a lane below, so a
178
+ * configurator's visitor never waits behind an overnight catalog.
179
+ */
180
+ declare const RENDER_LANES: readonly ["interactive", "normal", "batch"];
181
+ type RenderLane = (typeof RENDER_LANES)[number];
182
+ type RenderRecord = {
183
+ id: string;
184
+ state: RenderState;
185
+ progress: number;
186
+ /**
187
+ * A video's frames traced so far and in all, while it renders. Updated
188
+ * every ten seconds or so; absent for a still and once the render ends.
189
+ */
190
+ frames?: {
191
+ done: number;
192
+ total: number;
193
+ };
194
+ /** Which of the account's queues it waits in. */
195
+ lane?: RenderLane;
196
+ /**
197
+ * How many times a worker has been handed this render. 1 is the normal
198
+ * case; more means an infrastructure failure was retried for you.
199
+ */
200
+ attempts?: number;
201
+ /** The batch this render belongs to, and its key within it. */
202
+ batchId?: string;
203
+ batchKey?: string;
204
+ /** A low-sample image, available long before the final one. */
205
+ previewUrl?: string;
206
+ result?: RenderResult;
207
+ error?: RenderError;
208
+ estimate?: CostEstimate;
209
+ createdAt: number;
210
+ updatedAt: number;
211
+ metadata?: Record<string, unknown>;
212
+ };
213
+ /**
214
+ * A finished bake, as `GET /v1/bakes/:id` answers it.
215
+ *
216
+ * The bundle's uv arrays are behind `bundleUrl`, not here: a dense room's
217
+ * are megabytes, and the SDK reads them once from storage. `files` is every
218
+ * name the bundle uses, resolved to a signed URL, so a loader can take
219
+ * `bundle.objects[i].lightmap.uri` and look it up without knowing where the
220
+ * files live. All of them expire together, at `expiresAt`.
221
+ */
222
+ type BakeResult = {
223
+ /** Signed GET for bundle.json: the BakeBundle, uv arrays and all. */
224
+ bundleUrl: string;
225
+ /** Every file the bundle names, by that name, as a signed GET. */
226
+ files: Record<string, string>;
227
+ /** Millisecond epoch at which the URLs stop working. */
228
+ expiresAt: number;
229
+ /**
230
+ * The bundle without its uv arrays: what a panel shows before it fetches
231
+ * anything.
232
+ */
233
+ summary: BakeBundleSummary;
234
+ /** Every file's size together, in bytes. */
235
+ bytes: number;
236
+ cost: number;
237
+ versions: Record<string, string | number>;
238
+ };
239
+ type BakeRecord = {
240
+ id: string;
241
+ state: RenderState;
242
+ progress: number;
243
+ result?: BakeResult;
244
+ error?: RenderError;
245
+ estimate?: CostEstimate;
246
+ createdAt: number;
247
+ updatedAt: number;
248
+ metadata?: Record<string, unknown>;
249
+ };
250
+ /**
251
+ * Cost, before anything expensive happens.
252
+ *
253
+ * `maximum` is what `maxCost` is compared against, so a developer who sets
254
+ * a ceiling gets a refusal rather than a bill somewhere between the two
255
+ * numbers.
256
+ */
257
+ type CostEstimate = {
258
+ estimatedCost: number;
259
+ maximumCost: number;
260
+ estimatedSeconds: number;
261
+ compatibilityScore: number;
262
+ };
263
+ /**
264
+ * A failure a developer can act on.
265
+ *
266
+ * `code` is stable and machine-readable; `message`, `why` and `fix` are for
267
+ * the developer. A traceback is never any of them.
268
+ */
269
+ type RenderError = {
270
+ code: RenderErrorCode;
271
+ message: string;
272
+ why?: string;
273
+ fix?: string;
274
+ docs?: string;
275
+ /** Where in the scene, when the failure has a location. */
276
+ path?: string;
277
+ /** Whether resubmitting unchanged could plausibly work. */
278
+ retryable: boolean;
279
+ /**
280
+ * The control plane tried this render again and gave up: every attempt
281
+ * failed the same retryable way. We have been told, and
282
+ * `POST /v1/renders/:id/retry` tries once more on request.
283
+ */
284
+ attemptsExhausted?: boolean;
285
+ };
286
+ declare const RENDER_ERROR_CODES: readonly ["RenderBudgetExceeded", "UnsupportedMaterial", "SceneTooLarge", "TextureTooLarge", "AssetNotFound", "AssetUploadIncomplete", "ProtocolVersionUnsupported", "RoomPresetUnknown", "RoomPresetBuildMismatch", "CompatibilityPreflightFailed", "OutOfVideoMemory", "RenderTimeout", "WorkerFailure", "WorkerLost", "RendererCrashed", "UploadFailed", "ResultLost", "CapacityUnavailable", "QueueFull", "QueueTimeout", "BatchBudgetExceeded", "BatchClosed", "ImportRefused", "ImportFailed", "PlanRequired", "StorageUnavailable", "InsufficientBalance", "QuotaExceeded", "ConcurrencyLimitReached", "RateLimited", "Unauthorized", "TokenExpired", "OriginNotAllowed", "InvalidRequest"];
287
+ type RenderErrorCode = (typeof RENDER_ERROR_CODES)[number];
288
+ /** Webhook event names. */
289
+ declare const WEBHOOK_EVENTS: readonly ["render.created", "render.started", "render.preview", "render.completed", "render.failed", "render.cancelled", "render.retrying", "video.started", "video.frame.completed", "video.completed", "bake.created", "bake.started", "bake.completed", "bake.failed", "bake.cancelled", "bake.retrying", "batch.progress", "batch.completed", "batch.paused"];
290
+ type WebhookEvent = (typeof WEBHOOK_EVENTS)[number];
291
+ /**
292
+ * What a webhook carries. A `render.*` event has `render`; a `bake.*` event
293
+ * has `bake`. Never both: a receiver switches on `event` and reads the one
294
+ * record the event is about.
295
+ */
296
+ type WebhookPayload = {
297
+ event: WebhookEvent;
298
+ /** Millisecond epoch. Signed together with the body; see the docs. */
299
+ sentAt: number;
300
+ render?: RenderRecord;
301
+ bake?: BakeRecord;
302
+ /** A `batch.*` event carries the batch's ledger instead. */
303
+ batch?: BatchRecord;
304
+ };
305
+
306
+ type AssetKind = 'scene' | 'texture' | 'hdri' | 'ies' | 'geometry' | 'animation';
307
+ type AssetDescriptor = {
308
+ hash: string;
309
+ kind: AssetKind;
310
+ bytes: number;
311
+ contentType: string;
312
+ /** Diagnostics and the devtools' upload list; never used for addressing. */
313
+ name?: string;
314
+ };
315
+ /** Request body for "which of these do you already have?". */
316
+ type AssetCheckRequest = {
317
+ assets: AssetDescriptor[];
318
+ };
319
+ /**
320
+ * The answer, plus a signed PUT for each miss.
321
+ *
322
+ * The presigned URL is a capability, not a credential: one object, one
323
+ * method, one expiry. It lets the browser upload straight to storage without
324
+ * the control plane ever touching the bytes.
325
+ */
326
+ type AssetCheckResponse = {
327
+ /** Hashes already in storage. Do not upload these. */
328
+ present: string[];
329
+ /** One signed PUT per hash that is missing. */
330
+ uploads: Array<{
331
+ hash: string;
332
+ url: string;
333
+ /**
334
+ * Headers the signature covers. A presigned PUT is signed over an exact
335
+ * header set, so sending more or fewer than these is a 403. Pass them
336
+ * through verbatim.
337
+ */
338
+ headers?: Record<string, string>;
339
+ expiresAt: number;
340
+ }>;
341
+ };
342
+ /**
343
+ * `DELETE /v1/assets/:hash`. Secret key only. The stored file and its
344
+ * record are gone; the next render that needs it uploads it again.
345
+ */
346
+ type AssetDeleteResponse = {
347
+ hash: string;
348
+ /** False when the project held no file with this hash: not an error. */
349
+ deleted: boolean;
350
+ };
351
+
352
+ /**
353
+ * What a GLB says about itself, read from its JSON chunk alone.
354
+ *
355
+ * A scene the SDK captured arrives with everything the control plane needs
356
+ * beside it: a triangle count to price with, a camera, a compatibility
357
+ * report. A model fetched by URL arrives with nothing, and the renderer is
358
+ * the wrong place to find out it cannot be read: that is a refusal at three
359
+ * in the morning, a thousand times. So the import reads the file's own
360
+ * table of contents, which is the first chunk and a few hundred KB at most,
361
+ * and answers before anything is admitted:
362
+ *
363
+ * - how heavy it is (triangles, per node instance, the way it will trace);
364
+ * - where it is (the world bounds, from accessor min/max through the node
365
+ * transforms), which is what lets a camera be FRAMED instead of guessed;
366
+ * - which cameras it carries, by name;
367
+ * - what in it the renderer cannot read (a required extension its importer
368
+ * does not implement), by name and with the fix.
369
+ *
370
+ * Pure, no dependencies, no binary chunk: nothing here decodes geometry.
371
+ */
372
+
373
+ type GlbCamera = {
374
+ /** The node's name, or the camera's. What a caller asks for it by. */
375
+ name: string;
376
+ /** As it stands in the file, in world space. `aspect` is the file's own, when it gives one. */
377
+ camera: CameraSpec;
378
+ };
379
+ type GlbFacts = {
380
+ bytes: number;
381
+ /** Counted per node instance: a mesh two nodes show is traced twice. */
382
+ triangles: number;
383
+ meshes: number;
384
+ materials: number;
385
+ textures: number;
386
+ /** Punctual lights the file carries. They render as its author set them. */
387
+ lights: number;
388
+ animations: number;
389
+ /** World bounds of everything with geometry, or null for a file with none. */
390
+ bounds: {
391
+ min: Vec3;
392
+ max: Vec3;
393
+ } | null;
394
+ cameras: GlbCamera[];
395
+ /** Named nodes, in file order, bounded. */
396
+ objects: string[];
397
+ extensionsUsed: string[];
398
+ extensionsRequired: string[];
399
+ generator?: string;
400
+ /** `error` issues mean the renderer cannot read the file as authored. */
401
+ issues: CompatibilityIssue[];
402
+ };
403
+
404
+ /**
405
+ * Importing an asset by URL: `POST /v1/assets/import`.
406
+ *
407
+ * Every other asset is pushed: the browser hashes it and PUTs it on a
408
+ * presigned URL. A catalog that already sits on a CDN should not be pulled
409
+ * through somebody's laptop to be pushed again, so this one is pulled: the
410
+ * control plane fetches the public URL once, stores the bytes content
411
+ * addressed exactly as an upload would have, and answers with the hash and
412
+ * what the file says about itself. The result is an ordinary asset, and
413
+ * everything after it (the manifest, the cache keys, the render) is the
414
+ * ordinary path.
415
+ *
416
+ * Fetching a URL a customer names is the one thing here a stranger could aim
417
+ * somewhere else, so the route takes a secret key only (never a browser
418
+ * token), and the fetch is fenced: https, public addresses only, no
419
+ * credentials in the URL, and a size limit.
420
+ */
421
+
422
+ type AssetImportKind = 'scene' | 'hdri';
423
+ type AssetImportRequest = {
424
+ /** `https://`, public, no credentials in it. */
425
+ url: string;
426
+ /** `scene` (a GLB, the default) or `hdri` (a Radiance .hdr or an OpenEXR). */
427
+ kind?: AssetImportKind;
428
+ };
429
+ type AssetImportResponse = {
430
+ hash: AssetHash;
431
+ kind: AssetImportKind;
432
+ bytes: number;
433
+ /**
434
+ * True when nothing was downloaded: the URL answered 304 to the validator
435
+ * kept from the last import, so the stored bytes are still what it serves.
436
+ */
437
+ unchanged: boolean;
438
+ /** For a `scene`: what the GLB says about itself. */
439
+ facts?: GlbFacts;
440
+ };
441
+
442
+ /**
443
+ * Errors a developer can act on.
444
+ *
445
+ * "Render failed" is a bad error. A traceback is a worse one. Every failure
446
+ * that reaches the developer carries what went wrong, where, why, and what to
447
+ * do about it, and `code` stays stable so the failure can also be branched on
448
+ * in code.
449
+ */
450
+
451
+ /**
452
+ * Codes the SDK can raise that the render protocol does not: a fault on the
453
+ * way (`NetworkError`), a fault before anything left the browser
454
+ * (`CaptureFailed`), the two refusals a batch page can meet as a whole (over
455
+ * the batch's own ceiling, or after it was sealed), and the two ends of a job
456
+ * that are not faults in the scene: it was cancelled (`Cancelled`), or its
457
+ * files were deleted before it was read (`Expired`).
458
+ */
459
+ type Bakery3ErrorCode = RenderErrorCode | 'NetworkError' | 'CaptureFailed' | 'BatchBudgetExceeded' | 'BatchClosed' | 'Cancelled' | 'Expired';
460
+ declare class Bakery3Error extends Error {
461
+ readonly code: Bakery3ErrorCode;
462
+ readonly why?: string;
463
+ readonly fix?: string;
464
+ readonly docs?: string;
465
+ readonly path?: string;
466
+ readonly retryable: boolean;
467
+ constructor(init: {
468
+ code: Bakery3ErrorCode;
469
+ message: string;
470
+ why?: string;
471
+ fix?: string;
472
+ docs?: string;
473
+ path?: string;
474
+ retryable?: boolean;
475
+ });
476
+ static from(error: RenderError): Bakery3Error;
477
+ /**
478
+ * The multi-line form, for a console or a devtools panel.
479
+ *
480
+ * `Error.message` stays one line so it reads correctly everywhere a message
481
+ * is expected to be one: a log aggregator, a toast, a test name. `stack`
482
+ * starts with this form, so an uncaught error prints its fix.
483
+ */
484
+ toDisplayString(): string;
485
+ }
486
+ /** What was refused, so the refusal can say which dials bring the price down. */
487
+ type BudgetedKind = 'render' | 'video' | 'bake';
488
+ /**
489
+ * What a budget refusal can say. Every field is optional, because a refusal
490
+ * from the API may carry fewer numbers than the SDK's own check knows.
491
+ */
492
+ type RenderBudgetInit = {
493
+ message?: string;
494
+ why?: string;
495
+ fix?: string;
496
+ docs?: string;
497
+ /** The ceiling that was set. */
498
+ maxCost?: number;
499
+ estimatedCost?: number;
500
+ maximumCost?: number;
501
+ kind?: BudgetedKind;
502
+ };
503
+ /**
504
+ * The budget refusal.
505
+ *
506
+ * Its own class because it is the one failure a developer is expected to
507
+ * catch by type rather than by code: it is a normal, designed outcome of
508
+ * setting `maxCost`, not a fault. Nothing was sent to a renderer and nothing
509
+ * was charged.
510
+ *
511
+ * `instanceof RenderBudgetExceeded` catches both ways it is raised: the SDK's
512
+ * own check before an upload (`new RenderBudgetExceeded(maxCost, quote,
513
+ * kind)`, every number known), and the API's 402 (`new
514
+ * RenderBudgetExceeded({ ... })`, with whatever numbers that answer carried,
515
+ * for example from a browser token that has spent its allowance).
516
+ */
517
+ declare class RenderBudgetExceeded extends Bakery3Error {
518
+ /** The ceiling that was set, when known. */
519
+ readonly maxCost?: number;
520
+ readonly estimatedCost?: number;
521
+ /** The ceiling the job would have been accepted under: the number `maxCost` is held against. */
522
+ readonly maximumCost?: number;
523
+ readonly kind: BudgetedKind;
524
+ constructor(maxCost: number, quote: {
525
+ estimatedCost: number;
526
+ maximumCost: number;
527
+ }, kind?: BudgetedKind);
528
+ constructor(init: RenderBudgetInit);
529
+ }
530
+ /**
531
+ * A whole page of batch items was refused.
532
+ *
533
+ * Admission is per page: the control plane prices the page, checks it against
534
+ * the account's balance and the batch's own `maxCost`, and either admits
535
+ * every item or none. A `402 InsufficientBalance`, a `402 BatchBudgetExceeded`
536
+ * or a `409 BatchClosed` means nothing in the page was admitted. The `Batch`
537
+ * keeps those items buffered, so after a top-up (or a higher ceiling)
538
+ * `flush()` sends exactly the same page again.
539
+ *
540
+ * `admitted` is what earlier pages of the same flush already got through:
541
+ * those items are the server's now, and this error carries their outcomes so
542
+ * a caller does not lose them because a later page was refused.
543
+ */
544
+ declare class BatchPageRefused extends Bakery3Error {
545
+ /** The page that was refused whole, still in the batch's buffer. */
546
+ readonly page: BatchItemRequest[];
547
+ /** Outcomes of the pages this flush admitted before the refusal. */
548
+ readonly admitted: BatchItemOutcome[];
549
+ constructor(cause: Bakery3Error, page: BatchItemRequest[], admitted: BatchItemOutcome[]);
550
+ }
551
+
552
+ /**
553
+ * The HTTP client for the control plane.
554
+ *
555
+ * Small on purpose: a handful of endpoints, one auth header, one error shape.
556
+ * The interesting work happens in the browser (capture, hashing) and on the
557
+ * render workers; this is the thin part in between.
558
+ *
559
+ * The one piece of policy it carries is the retry: a 429 or a 503 is the
560
+ * control plane saying "not now", and it is answered with a bounded, jittered
561
+ * wait rather than an error the developer has to write a loop around. Only
562
+ * requests that are safe to repeat are repeated (see `RequestOptions.retry`).
563
+ *
564
+ * In production no secret key reaches this file. The browser holds a
565
+ * short-lived, project-scoped, origin-restricted, spend-capped token minted by
566
+ * the developer's own server. `token` is a function rather than a string so
567
+ * it can be fetched again when one expires, which for a five-minute token in
568
+ * a long configurator session is routine.
569
+ *
570
+ * `apiKey` is the other door, and it is open on purpose: a key works from the
571
+ * browser so the first render is one paste away, and `warnIfKeyIsExposed`
572
+ * says once, with the replacement code, why it must not stay there.
573
+ *
574
+ * Neither is needed to construct a client: `check()` and `inspect()` never
575
+ * touch the network, and a React tree whose environment variable is unset
576
+ * must still mount. A missing credential is refused at the first request,
577
+ * with what to pass instead.
578
+ */
579
+
580
+ /** What `/v1/estimate` prices: a still or a clip, or a bake. */
581
+ type EstimateRequest = (Pick<RenderSpec, 'quality' | 'output' | 'advanced'> & {
582
+ /** Triangle count and texture footprint, so an estimate can be given
583
+ * before anything has been uploaded. `room` says the scene stands in a
584
+ * preset room, which the renderer builds around it; `enclosure` and
585
+ * `objects` say how walled in and how full it is from the camera
586
+ * (`SceneComplexity`), which is what makes an interior cost more. */
587
+ scene?: {
588
+ triangles?: number;
589
+ textureBytes?: number;
590
+ fog?: boolean;
591
+ room?: boolean;
592
+ enclosure?: number;
593
+ objects?: number;
594
+ };
595
+ /** Frames in a clip; the control plane prices a video per frame. */
596
+ frames?: number;
597
+ }) | {
598
+ /** The settings a bake request would carry. Texels (objects × size²)
599
+ * are what the control plane prices. */
600
+ bake: Pick<BakeSettings, 'quality' | 'textureSize' | 'include' | 'sizes' | 'atlas' | 'deliverGlb' | 'simplify' | 'shadow'> & {
601
+ /** The scene is a room interior: a ray that misses keeps going,
602
+ * which is most of what such a bake costs. */
603
+ enclosed?: boolean;
604
+ };
605
+ /** Triangles in the objects the bake would cover: what the unwrap runs
606
+ * over, and priced separately from the scene's own count. */
607
+ bakedTriangles?: number;
608
+ scene?: {
609
+ triangles?: number;
610
+ textureBytes?: number;
611
+ fog?: boolean;
612
+ };
613
+ };
614
+ /** A browser token: the string, or the JSON `tokens.create()` answers with. */
615
+ type MintedToken = string | {
616
+ token: string;
617
+ expiresAt?: number;
618
+ };
619
+ type TokenProvider = () => MintedToken | Promise<MintedToken>;
620
+ /**
621
+ * One of the two, never both. Neither is allowed too, for a client that only
622
+ * checks scenes; its first request is refused with what to pass.
623
+ *
624
+ * The `?: never` arms turn passing both into a type error at the call site
625
+ * rather than a runtime throw later: the two are different integrations, and
626
+ * a codebase carrying both is one that has not finished moving off the key.
627
+ */
628
+ type ClientAuth = {
629
+ /** Mints a browser token, usually from your own `/api/bakery3-token`. */
630
+ token: TokenProvider;
631
+ apiKey?: never;
632
+ } | {
633
+ /**
634
+ * A `bk_sk_` key used directly, for local testing, a Node script, or a
635
+ * server-rendered call.
636
+ *
637
+ * From a browser this ships the key to every visitor. The SDK allows it
638
+ * so the first render is one paste away, warns about it in the console,
639
+ * and expects `token` by the time you deploy.
640
+ *
641
+ * `undefined` (an environment variable that is not set) is accepted
642
+ * here and refused at the first request, with that said.
643
+ */
644
+ apiKey: string | undefined;
645
+ token?: never;
646
+ } | {
647
+ token?: undefined;
648
+ apiKey?: undefined;
649
+ };
650
+ /**
651
+ * How a 429 or a 503 is waited out. Bounded: after `maxTries` the error is
652
+ * the developer's. The defaults are the SDK's; a test shortens the delays.
653
+ */
654
+ type RetryPolicy = {
655
+ /** Attempts in total, the first included. Default 5. */
656
+ maxTries?: number;
657
+ /** The first wait, before jitter and doubling. Default 500 ms. */
658
+ baseDelayMs?: number;
659
+ /** No single wait is longer than this, `Retry-After` included. Default 30 s. */
660
+ maxDelayMs?: number;
661
+ };
662
+ type ClientOptions = ClientAuth & {
663
+ baseUrl?: string;
664
+ fetch?: typeof fetch;
665
+ retry?: RetryPolicy;
666
+ };
667
+ /** Per-request knobs, for the client's own methods. */
668
+ type RequestOptions = {
669
+ /**
670
+ * Whether a 429/503 may be answered by sending the request again.
671
+ *
672
+ * Every GET is. A POST is only when repeating it cannot do a second thing:
673
+ * a batch page (its items carry keys), a batch action, a render that
674
+ * carries an `idempotencyKey`. `POST /v1/renders` without one is not: a
675
+ * second copy would be a second charge, which no amount of backoff is
676
+ * worth.
677
+ */
678
+ retry?: boolean;
679
+ /** Cuts a long-poll short. */
680
+ signal?: AbortSignal;
681
+ };
682
+ /** `GET /v1/batches/:id/items`: the render record plus the item's key. */
683
+ type BatchItemRecord = RenderRecord & {
684
+ key: string;
685
+ };
686
+ type BatchItemsPage = {
687
+ items: BatchItemRecord[];
688
+ cursor: string | null;
689
+ };
690
+ type BatchAction = 'close' | 'pause' | 'resume' | 'cancel' | 'retry';
691
+ declare class Bakery3Client {
692
+ private readonly baseUrl;
693
+ private readonly auth;
694
+ /**
695
+ * The fetch this client sends with: the one passed in `options.fetch`, or
696
+ * the global. Uploads and bundle reads use it too, so a test, a proxy or a
697
+ * runtime with its own fetch sees every request the SDK makes.
698
+ */
699
+ readonly fetch: typeof fetch;
700
+ /** Cached until it expires. Re-minting per render would add a round trip to
701
+ * the developer's own server on the critical path of every click. */
702
+ private cached;
703
+ /** One token fetch at a time. React's StrictMode mounts twice, and two
704
+ * renders at once both find the cache empty: they share this one. */
705
+ private minting;
706
+ /**
707
+ * The browser token each render, bake and batch was created with, by id.
708
+ *
709
+ * A token can only read the rows it created. Once it has spent its
710
+ * allowance or expired, the API still lets it read and cancel those rows
711
+ * (for 24 hours past expiry) but not create more, and a freshly minted
712
+ * token cannot read them at all. So a job polls with the token that
713
+ * started it, whatever the local cache thinks of that token's expiry.
714
+ */
715
+ private readonly owners;
716
+ private readonly retry;
717
+ private readonly sendVersion;
718
+ constructor(options?: ClientOptions);
719
+ /**
720
+ * Why this client cannot make a request, or null when it can. The same
721
+ * error its first request would throw, for a panel or a status line that
722
+ * wants to say so before anyone presses Render.
723
+ */
724
+ credentialError(): Bakery3Error | null;
725
+ token(force?: boolean): Promise<string>;
726
+ private mint;
727
+ checkAssets(body: AssetCheckRequest): Promise<AssetCheckResponse>;
728
+ /**
729
+ * `POST /v1/assets/import`: have the service fetch a public URL into the
730
+ * project's assets. Secret key only. Safe to repeat: the same bytes are the
731
+ * same asset, and an unchanged URL is answered without a download.
732
+ */
733
+ importAsset(body: AssetImportRequest): Promise<AssetImportResponse>;
734
+ estimate(body: EstimateRequest): Promise<CostEstimate>;
735
+ createRender(body: RenderSpec): Promise<RenderRecord>;
736
+ /**
737
+ * A render's record, with fresh signed URLs for its result and preview.
738
+ * Read with the token that created it, when this client created it.
739
+ */
740
+ getRender(id: string, options?: {
741
+ signal?: AbortSignal;
742
+ }): Promise<RenderRecord>;
743
+ cancelRender(id: string): Promise<RenderRecord>;
744
+ /**
745
+ * `POST /v1/renders/:id/retry`: one more attempt for a dead-lettered render.
746
+ * Answers 201 with a new render linked to the old one, or 409 when the
747
+ * render is not dead-lettered. Not repeated on a 429/503: it creates a
748
+ * render, and a duplicate would be a duplicate charge.
749
+ */
750
+ retryRender(id: string): Promise<RenderRecord>;
751
+ createBake(body: BakeSpec): Promise<BakeRecord>;
752
+ getBake(id: string, options?: {
753
+ signal?: AbortSignal;
754
+ }): Promise<BakeRecord>;
755
+ cancelBake(id: string): Promise<BakeRecord>;
756
+ /** `POST /v1/batches`. The key is the idempotency key: the same key
757
+ * re-opens the same batch (200) while it is not terminal. */
758
+ openBatch(body: BatchOpenRequest): Promise<BatchRecord>;
759
+ /**
760
+ * `GET /v1/batches/:id`. With `wait`, long-polls for up to that many
761
+ * seconds (at most 25) until the counts change: the one poll a batch needs.
762
+ */
763
+ getBatch(id: string, options?: {
764
+ wait?: number;
765
+ signal?: AbortSignal;
766
+ }): Promise<BatchRecord>;
767
+ /**
768
+ * `POST /v1/batches/:id/items`: one page, at most `BATCH_PAGE_SIZE`.
769
+ *
770
+ * Every item carries its own key, so the page is safe to send twice: the
771
+ * second copy adopts what the first admitted. A refusal of the whole page
772
+ * (402 InsufficientBalance / BatchBudgetExceeded, 409 BatchClosed) throws;
773
+ * a problem with one item comes back inside `items[i].error` with a 200.
774
+ */
775
+ addBatchItems(id: string, body: BatchAddRequest): Promise<BatchAddResponse>;
776
+ /** `GET /v1/batches/:id/items?state=&cursor=&limit=`. */
777
+ listBatchItems(id: string, options?: {
778
+ state?: RenderState;
779
+ cursor?: string;
780
+ limit?: number;
781
+ }): Promise<BatchItemsPage>;
782
+ /**
783
+ * `GET /v1/batches/:id/export`: the ledger as NDJSON, one line per item,
784
+ * yielded as it streams so a ten-thousand-item batch is never one string.
785
+ */
786
+ exportBatch(id: string): AsyncIterable<BatchExportLine>;
787
+ /** `POST /v1/batches/:id/{close,pause,resume,cancel,retry}`. Every one is a
788
+ * state transition the control plane treats idempotently, so all repeat. */
789
+ batchAction(id: string, action: BatchAction): Promise<BatchRecord>;
790
+ private post;
791
+ /** A request about a row this client may have created, with its token. */
792
+ private read;
793
+ /** Remember which token created a row, so the row is read with it. */
794
+ private remember;
795
+ /**
796
+ * One authenticated JSON request, with the 401 re-mint and the 429/503
797
+ * backoff. Public for the server SDK, which shares the transport; the
798
+ * typed methods above are the API.
799
+ */
800
+ request<T>(method: string, path: string, body?: unknown, options?: RequestOptions): Promise<T>;
801
+ /** A JSON request, and the credential that got the answer. */
802
+ private call;
803
+ private send;
804
+ private fetchOnce;
805
+ /**
806
+ * Exponential with full jitter, or the server's own `Retry-After` when it
807
+ * sent one: a server that says "in 3 s" knows more than a formula does.
808
+ * Both are capped, so a header naming next Tuesday does not hang a page.
809
+ */
810
+ private delayFor;
811
+ }
812
+
813
+ /**
814
+ * A batch, from the customer's side.
815
+ *
816
+ * const batch = await bakery3.batches.open({ key: 'fall-2026-v3', maxCost: 600 });
817
+ * for await (const item of source) await batch.write(item); // a full page sends itself
818
+ * await batch.close(); // the tail is flushed, then sealed: the total is known
819
+ * await batch.wait({ onProgress: (p) => console.log(`${p.completed}/${p.total}`) });
820
+ * for await (const item of batch.items({ state: 'failed' })) console.error(item.key);
821
+ *
822
+ * Two things this class is careful about, because they are the whole reason
823
+ * the batch exists rather than a loop over `render()`:
824
+ *
825
+ * - Memory. `write` buffers a few KB of manifest per item and sends a page
826
+ * the moment one is full, by count or by bytes, so awaiting it is the
827
+ * backpressure and nothing here ever holds the catalog. (`add` and
828
+ * `flush` are the same two steps taken by hand.) A refused page stays
829
+ * buffered: the caller tops up and flushes again, and the same items go,
830
+ * under the same keys.
831
+ * - One poll loop. `wait` long-polls the batch record; it never polls a
832
+ * render. Items are read by state with a cursor when they are wanted.
833
+ */
834
+
835
+ /** The slice of the client a batch drives: what a mock has to provide. */
836
+ type BatchTransport = {
837
+ getBatch(id: string, options?: {
838
+ wait?: number;
839
+ signal?: AbortSignal;
840
+ }): Promise<BatchRecord>;
841
+ addBatchItems(id: string, body: BatchAddRequest): Promise<{
842
+ batch: BatchRecord;
843
+ items: BatchItemOutcome[];
844
+ }>;
845
+ listBatchItems(id: string, options?: {
846
+ state?: RenderState;
847
+ cursor?: string;
848
+ limit?: number;
849
+ }): Promise<BatchItemsPage>;
850
+ exportBatch(id: string): AsyncIterable<BatchExportLine>;
851
+ batchAction(id: string, action: 'close' | 'pause' | 'resume' | 'cancel' | 'retry'): Promise<BatchRecord>;
852
+ };
853
+ /**
854
+ * The counts, the cost and where the batch stands: what a status line
855
+ * prints. Flat on purpose (`p.completed`, not `p.counts.completed`).
856
+ */
857
+ type BatchProgress = BatchCounts & {
858
+ id: string;
859
+ state: BatchState;
860
+ /** Every item ever admitted, adopted included. Final once sealed. */
861
+ total: number;
862
+ /** How many are terminal. */
863
+ done: number;
864
+ cost: BatchCost;
865
+ pausedReason?: string;
866
+ };
867
+ type FlushOptions = {
868
+ /** Price the pages, admit nothing: the buffer stays for a real flush. */
869
+ dryRun?: boolean;
870
+ };
871
+ type WaitOptions = {
872
+ /** Called after every poll that returned, whether or not the counts moved. */
873
+ onProgress?: (progress: BatchProgress) => void;
874
+ signal?: AbortSignal;
875
+ };
876
+ declare class Batch {
877
+ readonly id: string;
878
+ readonly key: string;
879
+ private latest;
880
+ /** The flush in flight, or the last one, settled either way. */
881
+ private flushing;
882
+ private readonly buffer;
883
+ /** `buffer[i]` as JSON is about `sizes[i]` bytes. Kept beside it so a
884
+ * page can be closed on bytes without serializing anything twice. */
885
+ private readonly sizes;
886
+ private bytes;
887
+ private readonly client;
888
+ /** The clock `wait()` measures its patience with. A test turns it. */
889
+ private clock;
890
+ /** @internal `bakery3.batches.open()` and `.get()` make these. */
891
+ constructor(client: BatchTransport, record: BatchRecord);
892
+ /** Buffer an item. Nothing is sent until `flush()`. */
893
+ add(item: BatchItemRequest): this;
894
+ /**
895
+ * `add`, and send a page when one is full. Awaiting it is the
896
+ * backpressure: a loop over a file, a cursor or a generator of any length
897
+ * holds one page at most.
898
+ *
899
+ * for await (const item of source) await batch.write(item);
900
+ * await batch.close();
901
+ */
902
+ write(item: BatchItemRequest): Promise<void>;
903
+ /** Items added and not yet sent. */
904
+ get buffered(): number;
905
+ /** About how many bytes of JSON those items are. */
906
+ get bufferedBytes(): number;
907
+ /**
908
+ * Price items without buffering or admitting them: the estimate, the
909
+ * maximum and any refusal, per item, in the order given. Paged like a
910
+ * flush. An item already completed under its key is quoted as adopted, at
911
+ * nothing, which makes this the price of a re-run too.
912
+ */
913
+ quote(items: BatchItemRequest[]): Promise<BatchItemOutcome[]>;
914
+ /**
915
+ * Send the buffer in pages: `BATCH_PAGE_SIZE` items or `BATCH_PAGE_BYTES`
916
+ * of JSON, whichever a page reaches first.
917
+ *
918
+ * Returns one outcome per item sent: admitted, adopted, or refused alone
919
+ * (`outcome.error`). A page refused whole throws `BatchPageRefused` and
920
+ * leaves that page and everything behind it in the buffer, so the caller
921
+ * can top up and call `flush()` again; the error carries the outcomes of
922
+ * the pages that did get through.
923
+ */
924
+ flush(options?: FlushOptions): Promise<BatchItemOutcome[]>;
925
+ private flushNow;
926
+ /** Seal: no more items. `completed` fires once the last one is terminal.
927
+ * Anything still buffered is flushed first, because closing over unsent
928
+ * items would quietly drop the tail of a catalog. */
929
+ close(): Promise<BatchRecord>;
930
+ /** Stop feeding the queue; running items finish. */
931
+ pause(): Promise<BatchRecord>;
932
+ resume(): Promise<BatchRecord>;
933
+ /** Cancel every non-terminal item. What completed stays completed: it rendered. */
934
+ cancel(): Promise<BatchRecord>;
935
+ /** Re-queue every dead-lettered item, one new attempt each. */
936
+ retry(): Promise<BatchRecord>;
937
+ /** The latest record this batch has seen. No request. */
938
+ record(): BatchRecord;
939
+ /** Fetch the record now. */
940
+ refresh(): Promise<BatchRecord>;
941
+ /** Counts and cost from the latest record. No request. */
942
+ progress(): BatchProgress;
943
+ /**
944
+ * Wait for the batch to finish: one long-poll loop on the batch record
945
+ * until it is `completed` or `cancelled` (or sealed with every item
946
+ * terminal). Never a poll per render.
947
+ *
948
+ * A paused batch is waited on, not given up on (someone may resume it from
949
+ * the console), and `onProgress` sees `pausedReason` meanwhile. Pass
950
+ * `signal` to stop waiting; the batch itself is untouched.
951
+ *
952
+ * A fault that clears is ridden out. One that does not (five minutes with
953
+ * not one poll through) rejects with an error that says so and carries the
954
+ * last fault's code. The batch renders on regardless, and `wait()` can be
955
+ * called again.
956
+ */
957
+ wait(options?: WaitOptions): Promise<BatchRecord>;
958
+ /** Every item, or every item in one state, walked with the cursor. */
959
+ items(options?: {
960
+ state?: RenderState;
961
+ }): AsyncIterable<BatchItemRecord>;
962
+ /** The ledger, line by line, as the server streams it. */
963
+ export(): AsyncIterable<BatchExportLine>;
964
+ private apply;
965
+ }
966
+
967
+ /**
968
+ * A set of pictures: what every many-pictures call hands back.
969
+ *
970
+ * `render({ cameras })` and `renderVariants()` in the browser, and
971
+ * `renderBatch()` from Node, all record into a batch and return one of
972
+ * these, so a set of three and a catalog of six thousand are the same object
973
+ * with the same guarantees: one ceiling for all of it, one poll for all of
974
+ * it, results walked a page at a time and never held.
975
+ *
976
+ * No three.js here: the server entry imports this file.
977
+ */
978
+
979
+ /** One finished picture of a set. */
980
+ type RenderSetImage = {
981
+ /** The item's key: `variant/finish/camera`, as recorded. */
982
+ key: string;
983
+ /** The render's id. */
984
+ id: string;
985
+ variant?: string;
986
+ finish?: string;
987
+ camera?: string;
988
+ /** The shot this is, for a set recorded with shots. */
989
+ shot?: string;
990
+ /** `'video'` when the url is a clip. */
991
+ kind?: 'image' | 'video';
992
+ /** Signed and expiring. Copy the bytes; do not serve from it. */
993
+ url: string;
994
+ width: number;
995
+ height: number;
996
+ /** What this picture cost. Nothing, when it was adopted from an earlier run. */
997
+ cost: number;
998
+ metadata?: Record<string, unknown>;
999
+ result: RenderResult;
1000
+ };
1001
+ /** One picture that did not render, and why. */
1002
+ type RenderSetFailure = {
1003
+ key: string;
1004
+ id: string;
1005
+ variant?: string;
1006
+ finish?: string;
1007
+ camera?: string;
1008
+ shot?: string;
1009
+ error: Bakery3Error;
1010
+ metadata?: Record<string, unknown>;
1011
+ };
1012
+ /** One picture turned down when it was submitted: it has no render and never will. */
1013
+ type RenderSetRefusal = {
1014
+ key: string;
1015
+ variant?: string;
1016
+ finish?: string;
1017
+ camera?: string;
1018
+ shot?: string;
1019
+ error: RenderError;
1020
+ };
1021
+ /** What a recording did, in numbers small enough to keep. */
1022
+ type Recorded = {
1023
+ variants: number;
1024
+ images: number;
1025
+ /** Already rendered under their keys in an earlier run. Cost nothing. */
1026
+ adopted: number;
1027
+ /** Turned down alone at admission (a spec that does not parse, an item over its own ceiling). */
1028
+ refused: number;
1029
+ /** The first of those, with their reasons. Capped, because a broken pipeline refuses every item. */
1030
+ refusals: RenderSetRefusal[];
1031
+ };
1032
+ /** What a whole run would cost, from `quoteVariants()`. Nothing was admitted. */
1033
+ type VariantsQuote = Recorded & {
1034
+ /** Σ estimate over the pictures that would render. */
1035
+ estimated: number;
1036
+ /** Σ maximum: what admission would reserve, and the number to set `maxCost` from. */
1037
+ maximum: number;
1038
+ };
1039
+ declare class RenderSet {
1040
+ /** The batch underneath: pause, resume, retry, the export. */
1041
+ readonly batch: Batch;
1042
+ readonly id: string;
1043
+ readonly key: string;
1044
+ /** What the call that made this set recorded. Empty for a set fetched by id. */
1045
+ readonly recorded: Recorded;
1046
+ /** Item key → position, for a set small enough to have asked for an order. */
1047
+ private order?;
1048
+ constructor(batch: Batch, recorded?: Recorded);
1049
+ /** Counts and cost from the latest record. No request. */
1050
+ progress(): BatchProgress;
1051
+ /**
1052
+ * Until every picture is terminal. One long-poll on the set, however many
1053
+ * pictures it has. Resolves with the final counts: pictures that failed
1054
+ * are in `failures()`, they do not reject the wait.
1055
+ */
1056
+ wait(options?: WaitOptions): Promise<BatchProgress>;
1057
+ /**
1058
+ * Every finished picture, a page at a time. Safe on a set of any size,
1059
+ * and safe to call before the set is done: it walks what has completed
1060
+ * so far.
1061
+ */
1062
+ images(): AsyncIterable<RenderSetImage>;
1063
+ /**
1064
+ * Every picture that did not render, with the reason and the fix.
1065
+ * `error.retryable` tells the two kinds apart: false is a refusal, the
1066
+ * scene's fault and the same next time; true ran out of attempts on a
1067
+ * fault of ours, and `set.batch.retry()` queues it again.
1068
+ */
1069
+ failures(): AsyncIterable<RenderSetFailure>;
1070
+ /**
1071
+ * Wait, then every picture in one array, in camera order for a
1072
+ * `render({ cameras })`: one picture per camera, or a rejection. Rejects
1073
+ * with `RenderSetRefused` when a picture was turned down at submission
1074
+ * (it has no render, and the array would be one short with every later
1075
+ * picture in the wrong place), and otherwise with the first failure, as
1076
+ * `job.result()` does. The pictures that did render are still there:
1077
+ * walk `images()`, each named by its `camera`.
1078
+ *
1079
+ * It collects, so it is for a handful of pictures. For a catalog, walk
1080
+ * `images()`.
1081
+ */
1082
+ result(options?: WaitOptions): Promise<RenderSetImage[]>;
1083
+ /** Cancel every picture that has not finished. What completed, completed. */
1084
+ cancel(): Promise<void>;
1085
+ /** @internal */
1086
+ ordered(keys: string[]): this;
1087
+ }
1088
+ /**
1089
+ * Pictures of a set were turned down when they were submitted, so the set
1090
+ * cannot give one picture per camera (or per variant) in order.
1091
+ *
1092
+ * `refusals` says which and why. Its `code` is the first refusal's. The
1093
+ * pictures that were accepted render as usual: `set.images()` walks them.
1094
+ */
1095
+ declare class RenderSetRefused extends Bakery3Error {
1096
+ /** Which pictures, and why: the first fifty when a run refused more. */
1097
+ readonly refusals: Array<Omit<RenderSetRefusal, 'error'> & {
1098
+ error: Bakery3Error;
1099
+ }>;
1100
+ /** How many were refused in all. */
1101
+ readonly refused: number;
1102
+ /** How many pictures were asked for. */
1103
+ readonly requested: number;
1104
+ constructor(recorded: Recorded);
1105
+ }
1106
+
1107
+ /**
1108
+ * The test run: a few products, every camera, small and fast.
1109
+ *
1110
+ * Before six thousand pictures are paid for, three products are worth
1111
+ * looking at: are the cameras where they were meant to be, is the room the
1112
+ * right way round, does the finish list hide what it should. A test run is
1113
+ * the real run's own options with three changes, made here so the browser
1114
+ * and the server make the same ones:
1115
+ *
1116
+ * - A sample of the products. From an array: the first, the middle and the
1117
+ * last, because a catalog is usually sorted and its ends differ most.
1118
+ * From anything else (a generator, a cursor): the first three, since a
1119
+ * list that is never collected has no middle to ask for.
1120
+ * - Preview quality at a small size, the long edge 512 unless told
1121
+ * otherwise, the aspect kept, so the framing is the real run's framing.
1122
+ * - Its own keys. A test is looked at and thrown away; if it shared the real
1123
+ * run's keys, the real run would adopt these little previews as finished
1124
+ * pictures. Every test also differs from the last one, so a test after a
1125
+ * fix shows the fix and not yesterday's frame.
1126
+ *
1127
+ * No three.js here: the server entry imports this file.
1128
+ */
1129
+
1130
+ type TestRunOptions = {
1131
+ /** How many products. Default 3. */
1132
+ products?: number;
1133
+ /** The long edge of each picture, in pixels. Default 512. */
1134
+ size?: number;
1135
+ /** The ceiling for the test, in dollars. Default 5. */
1136
+ maxCost?: number;
1137
+ };
1138
+
1139
+ export { type AssetImportKind as A, type BatchProgress as B, type CostEstimate as C, type RenderError as D, type BakeRecord as E, type FlushOptions as F, type BakeResult as G, type ClientOptions as H, type Bakery3ErrorCode as I, type BatchAction as J, type BatchCost as K, type BatchCounts as L, type BatchState as M, type BudgetedKind as N, type ClientAuth as O, type MintedToken as P, type RenderBudgetInit as Q, type Recorded as R, type RenderSetRefusal as S, type TestRunOptions as T, RenderSetRefused as U, type VariantsQuote as V, type WebhookPayload as W, type BatchRecord as a, Batch as b, Bakery3Error as c, Bakery3Client as d, type RenderRecord as e, type BatchOpenRequest as f, type AssetImportResponse as g, type AssetDeleteResponse as h, type RetryPolicy as i, RenderSet as j, type BatchAddRequest as k, type BatchAddResponse as l, type BatchExportLine as m, type BatchItemOutcome as n, type BatchItemRecord as o, type BatchItemRequest as p, type BatchItemsPage as q, BatchPageRefused as r, type RenderSetFailure as s, type RenderSetImage as t, type WaitOptions as u, type RenderResult as v, type TokenProvider as w, RenderBudgetExceeded as x, type AssetDescriptor as y, type RenderState as z };