@printhive/api 0.2.0 → 0.4.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/CHANGELOG.md +23 -0
- package/README.md +209 -6
- package/dist/chunk-GOUMDFJR.js +27615 -0
- package/dist/{errors-TJFN2M7S.js → errors-4M56UUFV.js} +1 -1
- package/dist/index.cjs +19245 -5418
- package/dist/index.d.cts +3012 -140
- package/dist/index.d.ts +3012 -140
- package/dist/index.js +194 -22
- package/package.json +1 -1
- package/dist/chunk-7UULMDS5.js +0 -13947
package/dist/index.js
CHANGED
|
@@ -4,13 +4,20 @@ import {
|
|
|
4
4
|
apiError,
|
|
5
5
|
apiKey,
|
|
6
6
|
createRequest,
|
|
7
|
+
filamentSearch,
|
|
8
|
+
jobSnapshot,
|
|
7
9
|
model,
|
|
8
10
|
page,
|
|
11
|
+
preparation,
|
|
12
|
+
preparationDownload,
|
|
13
|
+
preparationInput,
|
|
9
14
|
printJob,
|
|
10
15
|
printer,
|
|
16
|
+
printerSearch,
|
|
11
17
|
printers,
|
|
18
|
+
reviewApproval,
|
|
12
19
|
source
|
|
13
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-GOUMDFJR.js";
|
|
14
21
|
|
|
15
22
|
// src/transport.ts
|
|
16
23
|
var MAX_RETRY_AFTER_MS = 6e4;
|
|
@@ -117,13 +124,93 @@ var Transport = class {
|
|
|
117
124
|
}
|
|
118
125
|
};
|
|
119
126
|
function retryDelay(failure, replayable, attempt, maxRetries) {
|
|
120
|
-
const retryable = failure instanceof PrintHiveApiError ? failure.status === 429 || failure.status === 503 : failure.reason === "network";
|
|
127
|
+
const retryable = failure instanceof PrintHiveApiError ? failure.code !== "preparation_disabled" && (failure.status === 429 || failure.status === 503) : failure.reason === "network";
|
|
121
128
|
if (!retryable || !replayable || attempt >= maxRetries) throw failure;
|
|
122
129
|
const retryAfterMs = failure instanceof PrintHiveApiError ? failure.retryAfterMs ?? 0 : 0;
|
|
123
130
|
if (retryAfterMs > MAX_RETRY_AFTER_MS) throw failure;
|
|
124
131
|
const backoff = Math.min(3e4, 250 * 2 ** attempt) * (0.5 + Math.random());
|
|
125
132
|
return Math.max(backoff, retryAfterMs);
|
|
126
133
|
}
|
|
134
|
+
async function decode(response, validate) {
|
|
135
|
+
const value = await response.json().catch((error) => {
|
|
136
|
+
if (error instanceof SyntaxError)
|
|
137
|
+
throw new TypeError("Invalid Print Hive API response");
|
|
138
|
+
throw error;
|
|
139
|
+
});
|
|
140
|
+
if (!validate(value)) throw new TypeError("Invalid Print Hive API response");
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/search.ts
|
|
145
|
+
function searchQuery(input) {
|
|
146
|
+
const query = new URLSearchParams({ q: input.query });
|
|
147
|
+
if (input.limit !== void 0) query.set("limit", String(input.limit));
|
|
148
|
+
if (input.offset !== void 0) query.set("offset", String(input.offset));
|
|
149
|
+
return query;
|
|
150
|
+
}
|
|
151
|
+
var ResourceSearch = class {
|
|
152
|
+
constructor(transport) {
|
|
153
|
+
this.transport = transport;
|
|
154
|
+
}
|
|
155
|
+
async printers(input) {
|
|
156
|
+
const query = searchQuery(input);
|
|
157
|
+
const page2 = await this.transport.request({
|
|
158
|
+
method: "GET",
|
|
159
|
+
path: "/v1/printers/search",
|
|
160
|
+
query,
|
|
161
|
+
signal: input.signal,
|
|
162
|
+
decode: (response) => decode(response, printerSearch)
|
|
163
|
+
});
|
|
164
|
+
return page2;
|
|
165
|
+
}
|
|
166
|
+
async filaments(input) {
|
|
167
|
+
const page2 = await this.transport.request({
|
|
168
|
+
method: "GET",
|
|
169
|
+
path: "/v1/filaments/search",
|
|
170
|
+
query: searchQuery(input),
|
|
171
|
+
signal: input.signal,
|
|
172
|
+
decode: (response) => decode(response, filamentSearch)
|
|
173
|
+
});
|
|
174
|
+
return page2;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/filament-catalog.ts
|
|
179
|
+
var FilamentCatalog = class {
|
|
180
|
+
constructor(transport) {
|
|
181
|
+
this.transport = transport;
|
|
182
|
+
}
|
|
183
|
+
upsert(input) {
|
|
184
|
+
const snapshot = JSON.stringify(input);
|
|
185
|
+
return this.transport.request({
|
|
186
|
+
method: "POST",
|
|
187
|
+
path: "/v1/filament-catalog",
|
|
188
|
+
contentType: "application/json",
|
|
189
|
+
body: async () => snapshot,
|
|
190
|
+
idempotencyKey: encodeURIComponent(input.externalId),
|
|
191
|
+
replayable: true,
|
|
192
|
+
decode: async (response) => response.json()
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
list(input = {}) {
|
|
196
|
+
const query = new URLSearchParams();
|
|
197
|
+
for (const [key, value] of Object.entries(input))
|
|
198
|
+
if (value !== void 0) query.set(key, String(value));
|
|
199
|
+
return this.transport.request({
|
|
200
|
+
method: "GET",
|
|
201
|
+
path: "/v1/filament-catalog",
|
|
202
|
+
query,
|
|
203
|
+
decode: async (response) => response.json()
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
get(id) {
|
|
207
|
+
return this.transport.request({
|
|
208
|
+
method: "GET",
|
|
209
|
+
path: `/v1/filament-catalog/${encodeURIComponent(id)}`,
|
|
210
|
+
decode: async (response) => response.json()
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
};
|
|
127
214
|
|
|
128
215
|
// src/print-jobs.ts
|
|
129
216
|
var PrintJobCreateStoppedError = class extends Error {
|
|
@@ -133,7 +220,7 @@ var PrintJobCreateStoppedError = class extends Error {
|
|
|
133
220
|
this.name = "PrintJobCreateStoppedError";
|
|
134
221
|
}
|
|
135
222
|
};
|
|
136
|
-
async function
|
|
223
|
+
async function decode2(response, validate) {
|
|
137
224
|
const value = await response.json().catch((error) => {
|
|
138
225
|
if (error instanceof SyntaxError)
|
|
139
226
|
throw new TypeError("Invalid Print Hive API response");
|
|
@@ -146,6 +233,19 @@ var PrintJobs = class {
|
|
|
146
233
|
constructor(transport) {
|
|
147
234
|
this.transport = transport;
|
|
148
235
|
}
|
|
236
|
+
async get(id, signal) {
|
|
237
|
+
if (!Number.isSafeInteger(id) || id < 1)
|
|
238
|
+
throw new RangeError("Print job id must be a positive safe integer");
|
|
239
|
+
const response = await this.transport.request({
|
|
240
|
+
method: "GET",
|
|
241
|
+
path: `/v1/print-jobs/${id}`,
|
|
242
|
+
signal,
|
|
243
|
+
decode: (response2) => decode2(response2, jobSnapshot)
|
|
244
|
+
});
|
|
245
|
+
if (response.job.id !== id)
|
|
246
|
+
throw new TypeError("Invalid Print Hive API response");
|
|
247
|
+
return response.job;
|
|
248
|
+
}
|
|
149
249
|
async create(input) {
|
|
150
250
|
const { idempotencyKey: suppliedKey, ...bodyInput } = input;
|
|
151
251
|
const idempotencyKey = suppliedKey ?? crypto.randomUUID();
|
|
@@ -171,6 +271,11 @@ var PrintJobs = class {
|
|
|
171
271
|
})) {
|
|
172
272
|
if (value !== void 0) form.set(field, value);
|
|
173
273
|
}
|
|
274
|
+
if (metadata.acceptEngineSettingUpdates !== void 0)
|
|
275
|
+
form.set(
|
|
276
|
+
"acceptEngineSettingUpdates",
|
|
277
|
+
JSON.stringify(metadata.acceptEngineSettingUpdates)
|
|
278
|
+
);
|
|
174
279
|
form.set("plate", String(metadata.plate));
|
|
175
280
|
form.set("filaments", JSON.stringify(metadata.filaments));
|
|
176
281
|
if (metadata.print_options !== void 0)
|
|
@@ -178,7 +283,7 @@ var PrintJobs = class {
|
|
|
178
283
|
form.set("file", new Blob([bytes]), filename);
|
|
179
284
|
return form;
|
|
180
285
|
},
|
|
181
|
-
decode: (response3) =>
|
|
286
|
+
decode: (response3) => decode2(response3, createRequest)
|
|
182
287
|
});
|
|
183
288
|
return { ...response2, idempotencyKey };
|
|
184
289
|
}
|
|
@@ -189,7 +294,7 @@ var PrintJobs = class {
|
|
|
189
294
|
replayable: true,
|
|
190
295
|
contentType: "application/json",
|
|
191
296
|
body: async () => JSON.stringify(bodyInput),
|
|
192
|
-
decode: (response2) =>
|
|
297
|
+
decode: (response2) => decode2(response2, printJob)
|
|
193
298
|
});
|
|
194
299
|
return { ...response, idempotencyKey };
|
|
195
300
|
}
|
|
@@ -198,7 +303,19 @@ var PrintJobs = class {
|
|
|
198
303
|
method: "GET",
|
|
199
304
|
path: `/v1/print-jobs/create-requests/${encodeURIComponent(requestId)}`,
|
|
200
305
|
signal,
|
|
201
|
-
decode: (response) =>
|
|
306
|
+
decode: (response) => decode2(response, createRequest)
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
approveReview(requestId, review, signal) {
|
|
310
|
+
return this.transport.request({
|
|
311
|
+
method: "POST",
|
|
312
|
+
path: `/v1/print-jobs/create-requests/${encodeURIComponent(requestId)}/approve-review`,
|
|
313
|
+
signal,
|
|
314
|
+
idempotencyKey: crypto.randomUUID(),
|
|
315
|
+
replayable: false,
|
|
316
|
+
contentType: "application/json",
|
|
317
|
+
body: async () => JSON.stringify(review),
|
|
318
|
+
decode: (response) => decode2(response, reviewApproval)
|
|
202
319
|
});
|
|
203
320
|
}
|
|
204
321
|
async waitUntilCreated(requestId, options = {}) {
|
|
@@ -224,15 +341,6 @@ var PrintJobs = class {
|
|
|
224
341
|
};
|
|
225
342
|
|
|
226
343
|
// src/index.ts
|
|
227
|
-
async function decode2(response, validate) {
|
|
228
|
-
const value = await response.json().catch((error) => {
|
|
229
|
-
if (error instanceof SyntaxError)
|
|
230
|
-
throw new TypeError("Invalid Print Hive API response");
|
|
231
|
-
throw error;
|
|
232
|
-
});
|
|
233
|
-
if (!validate(value)) throw new TypeError("Invalid Print Hive API response");
|
|
234
|
-
return value;
|
|
235
|
-
}
|
|
236
344
|
function isPath(file) {
|
|
237
345
|
return !(file instanceof Uint8Array) && !(file instanceof ReadableStream);
|
|
238
346
|
}
|
|
@@ -242,29 +350,93 @@ var PrintHive = class {
|
|
|
242
350
|
models;
|
|
243
351
|
printers;
|
|
244
352
|
printJobs;
|
|
353
|
+
filamentCatalog;
|
|
354
|
+
filaments;
|
|
355
|
+
preparations;
|
|
245
356
|
constructor(options) {
|
|
246
357
|
const transport = new Transport(options);
|
|
358
|
+
const search = new ResourceSearch(transport);
|
|
359
|
+
this.filaments = {
|
|
360
|
+
search: (input) => search.filaments(input)
|
|
361
|
+
};
|
|
247
362
|
this.printJobs = new PrintJobs(transport);
|
|
363
|
+
this.filamentCatalog = new FilamentCatalog(transport);
|
|
248
364
|
const get = (sourceId, signal) => transport.request({
|
|
249
|
-
decode: (response) =>
|
|
365
|
+
decode: (response) => decode(response, source),
|
|
250
366
|
method: "GET",
|
|
251
367
|
path: `${prefix}/uploads/${encodeURIComponent(sourceId)}`,
|
|
252
368
|
signal
|
|
253
369
|
});
|
|
370
|
+
const getPreparation = (id, signal) => transport.request({
|
|
371
|
+
decode: (response) => decode(response, preparation),
|
|
372
|
+
method: "GET",
|
|
373
|
+
path: `${prefix}/preparations/${encodeURIComponent(id)}`,
|
|
374
|
+
signal
|
|
375
|
+
});
|
|
376
|
+
this.preparations = {
|
|
377
|
+
get: getPreparation,
|
|
378
|
+
async create(input) {
|
|
379
|
+
const idempotencyKey = input.idempotencyKey ?? crypto.randomUUID();
|
|
380
|
+
const snapshot = JSON.stringify({ items: input.items });
|
|
381
|
+
if (!preparationInput(JSON.parse(snapshot)))
|
|
382
|
+
throw new TypeError("Invalid preparation input");
|
|
383
|
+
const preparation2 = await transport.request({
|
|
384
|
+
decode: (response) => decode(response, preparation),
|
|
385
|
+
method: "POST",
|
|
386
|
+
path: `${prefix}/preparations`,
|
|
387
|
+
contentType: "application/json",
|
|
388
|
+
body: async () => snapshot,
|
|
389
|
+
size: new TextEncoder().encode(snapshot).byteLength,
|
|
390
|
+
idempotencyKey,
|
|
391
|
+
replayable: true,
|
|
392
|
+
signal: input.signal
|
|
393
|
+
});
|
|
394
|
+
return { ...preparation2, idempotencyKey };
|
|
395
|
+
},
|
|
396
|
+
async waitUntilSettled(id, options2 = {}) {
|
|
397
|
+
const interval = positive(options2.intervalMs ?? 1e3, "intervalMs");
|
|
398
|
+
const deadline = AbortSignal.timeout(
|
|
399
|
+
positive(options2.timeoutMs ?? 12e4, "timeoutMs")
|
|
400
|
+
);
|
|
401
|
+
const signal = options2.signal ? AbortSignal.any([options2.signal, deadline]) : deadline;
|
|
402
|
+
try {
|
|
403
|
+
for (; ; ) {
|
|
404
|
+
const preparation2 = await getPreparation(id, signal);
|
|
405
|
+
const status = preparation2.status;
|
|
406
|
+
if (status === "ready" || status === "held" || status === "failed")
|
|
407
|
+
return { ...preparation2, status };
|
|
408
|
+
await pause(interval, signal);
|
|
409
|
+
}
|
|
410
|
+
} catch (error) {
|
|
411
|
+
if (deadline.aborted && !options2.signal?.aborted) {
|
|
412
|
+
const { PrintHiveNetworkError: PrintHiveNetworkError2 } = await import("./errors-4M56UUFV.js");
|
|
413
|
+
throw new PrintHiveNetworkError2("timeout");
|
|
414
|
+
}
|
|
415
|
+
throw error;
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
downloadInfo: (id, plateId, signal) => transport.request({
|
|
419
|
+
decode: (response) => decode(response, preparationDownload),
|
|
420
|
+
method: "GET",
|
|
421
|
+
path: `${prefix}/preparations/${encodeURIComponent(id)}/plates/${encodeURIComponent(plateId)}/download`,
|
|
422
|
+
signal
|
|
423
|
+
})
|
|
424
|
+
};
|
|
254
425
|
this.printers = {
|
|
426
|
+
search: (input) => search.printers(input),
|
|
255
427
|
list: (input = {}) => {
|
|
256
428
|
const query = new URLSearchParams();
|
|
257
429
|
if (input.limit !== void 0) query.set("limit", String(input.limit));
|
|
258
430
|
if (input.cursor !== void 0) query.set("cursor", input.cursor);
|
|
259
431
|
return transport.request({
|
|
260
|
-
decode: (response) =>
|
|
432
|
+
decode: (response) => decode(response, printers),
|
|
261
433
|
method: "GET",
|
|
262
434
|
path: "/v1/printers",
|
|
263
435
|
query
|
|
264
436
|
});
|
|
265
437
|
},
|
|
266
438
|
get: (id) => transport.request({
|
|
267
|
-
decode: (response) =>
|
|
439
|
+
decode: (response) => decode(response, printer),
|
|
268
440
|
method: "GET",
|
|
269
441
|
path: `/v1/printers/${encodeURIComponent(id)}`
|
|
270
442
|
})
|
|
@@ -302,7 +474,7 @@ var PrintHive = class {
|
|
|
302
474
|
if (!Number.isSafeInteger(size) || size < 0)
|
|
303
475
|
throw new RangeError("size must be a nonnegative safe integer");
|
|
304
476
|
const source2 = await transport.request({
|
|
305
|
-
decode: (response) =>
|
|
477
|
+
decode: (response) => decode(response, source),
|
|
306
478
|
method: "POST",
|
|
307
479
|
path: `${prefix}/uploads`,
|
|
308
480
|
query,
|
|
@@ -328,7 +500,7 @@ var PrintHive = class {
|
|
|
328
500
|
}
|
|
329
501
|
} catch (error) {
|
|
330
502
|
if (deadline.aborted && !options2.signal?.aborted) {
|
|
331
|
-
const { PrintHiveNetworkError: PrintHiveNetworkError2 } = await import("./errors-
|
|
503
|
+
const { PrintHiveNetworkError: PrintHiveNetworkError2 } = await import("./errors-4M56UUFV.js");
|
|
332
504
|
throw new PrintHiveNetworkError2("timeout");
|
|
333
505
|
}
|
|
334
506
|
throw error;
|
|
@@ -337,7 +509,7 @@ var PrintHive = class {
|
|
|
337
509
|
};
|
|
338
510
|
this.models = {
|
|
339
511
|
findByExternalId: (externalId) => transport.request({
|
|
340
|
-
decode: (response) =>
|
|
512
|
+
decode: (response) => decode(response, model),
|
|
341
513
|
method: "GET",
|
|
342
514
|
path: `${prefix}/models`,
|
|
343
515
|
query: new URLSearchParams({ externalId })
|
|
@@ -348,7 +520,7 @@ var PrintHive = class {
|
|
|
348
520
|
const query = new URLSearchParams();
|
|
349
521
|
if (cursor !== null) query.set("cursor", cursor);
|
|
350
522
|
const page2 = await transport.request({
|
|
351
|
-
decode: (response) =>
|
|
523
|
+
decode: (response) => decode(response, page),
|
|
352
524
|
method: "GET",
|
|
353
525
|
path: `${prefix}/models/${encodeURIComponent(modelId)}/files`,
|
|
354
526
|
query
|