@printhive/api 0.1.0 → 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.
package/dist/index.js CHANGED
@@ -3,10 +3,14 @@ import {
3
3
  PrintHiveNetworkError,
4
4
  apiError,
5
5
  apiKey,
6
+ createRequest,
6
7
  model,
7
8
  page,
9
+ printJob,
10
+ printer,
11
+ printers,
8
12
  source
9
- } from "./chunk-TGPYH7CV.js";
13
+ } from "./chunk-7UULMDS5.js";
10
14
 
11
15
  // src/transport.ts
12
16
  var MAX_RETRY_AFTER_MS = 6e4;
@@ -29,6 +33,14 @@ async function pause(ms, signal) {
29
33
  signal?.addEventListener("abort", abort, { once: true });
30
34
  });
31
35
  }
36
+ function postHeaders(request) {
37
+ const headers = new Headers({ "idempotency-key": request.idempotencyKey });
38
+ if (request.contentType !== null)
39
+ headers.set("content-type", request.contentType ?? "model/3mf");
40
+ if (request.size !== void 0)
41
+ headers.set("content-length", String(request.size));
42
+ return headers;
43
+ }
32
44
  var Transport = class {
33
45
  options;
34
46
  constructor(options) {
@@ -76,9 +88,8 @@ var Transport = class {
76
88
  redirect: "error"
77
89
  };
78
90
  if (request.method === "POST") {
79
- headers.set("content-type", "model/3mf");
80
- headers.set("content-length", String(request.size));
81
- headers.set("idempotency-key", request.idempotencyKey);
91
+ for (const [name, value] of postHeaders(request))
92
+ headers.set(name, value);
82
93
  init.body = await request.body();
83
94
  init.duplex = "half";
84
95
  }
@@ -114,7 +125,14 @@ function retryDelay(failure, replayable, attempt, maxRetries) {
114
125
  return Math.max(backoff, retryAfterMs);
115
126
  }
116
127
 
117
- // src/index.ts
128
+ // src/print-jobs.ts
129
+ var PrintJobCreateStoppedError = class extends Error {
130
+ constructor(request) {
131
+ super(`Print job creation ${request.status}`);
132
+ this.request = request;
133
+ this.name = "PrintJobCreateStoppedError";
134
+ }
135
+ };
118
136
  async function decode(response, validate) {
119
137
  const value = await response.json().catch((error) => {
120
138
  if (error instanceof SyntaxError)
@@ -124,6 +142,97 @@ async function decode(response, validate) {
124
142
  if (!validate(value)) throw new TypeError("Invalid Print Hive API response");
125
143
  return value;
126
144
  }
145
+ var PrintJobs = class {
146
+ constructor(transport) {
147
+ this.transport = transport;
148
+ }
149
+ async create(input) {
150
+ const { idempotencyKey: suppliedKey, ...bodyInput } = input;
151
+ const idempotencyKey = suppliedKey ?? crypto.randomUUID();
152
+ if ("file" in bodyInput) {
153
+ const { file, filename, ...metadata } = bodyInput;
154
+ const bytes = file instanceof Uint8Array ? new Uint8Array(file) : new Uint8Array(
155
+ await (await import("fs/promises")).readFile(file)
156
+ );
157
+ const response2 = await this.transport.request({
158
+ method: "POST",
159
+ path: "/v1/print-jobs/create",
160
+ idempotencyKey,
161
+ replayable: true,
162
+ contentType: null,
163
+ body: async () => {
164
+ const form = new FormData();
165
+ for (const [field, value] of Object.entries({
166
+ name: metadata.name,
167
+ printer_id: metadata.printer_id,
168
+ on_filament_mismatch: metadata.on_filament_mismatch,
169
+ externalId: metadata.externalId,
170
+ release: metadata.release
171
+ })) {
172
+ if (value !== void 0) form.set(field, value);
173
+ }
174
+ form.set("plate", String(metadata.plate));
175
+ form.set("filaments", JSON.stringify(metadata.filaments));
176
+ if (metadata.print_options !== void 0)
177
+ form.set("print_options", JSON.stringify(metadata.print_options));
178
+ form.set("file", new Blob([bytes]), filename);
179
+ return form;
180
+ },
181
+ decode: (response3) => decode(response3, createRequest)
182
+ });
183
+ return { ...response2, idempotencyKey };
184
+ }
185
+ const response = await this.transport.request({
186
+ method: "POST",
187
+ path: "/v1/print-jobs/create",
188
+ idempotencyKey,
189
+ replayable: true,
190
+ contentType: "application/json",
191
+ body: async () => JSON.stringify(bodyInput),
192
+ decode: (response2) => decode(response2, printJob)
193
+ });
194
+ return { ...response, idempotencyKey };
195
+ }
196
+ getCreateRequest(requestId, signal) {
197
+ return this.transport.request({
198
+ method: "GET",
199
+ path: `/v1/print-jobs/create-requests/${encodeURIComponent(requestId)}`,
200
+ signal,
201
+ decode: (response) => decode(response, createRequest)
202
+ });
203
+ }
204
+ async waitUntilCreated(requestId, options = {}) {
205
+ const interval = positive(options.intervalMs ?? 1e3, "intervalMs");
206
+ const deadline = AbortSignal.timeout(
207
+ positive(options.timeoutMs ?? 12e4, "timeoutMs")
208
+ );
209
+ const signal = options.signal ? AbortSignal.any([options.signal, deadline]) : deadline;
210
+ try {
211
+ for (; ; ) {
212
+ const request = await this.getCreateRequest(requestId, signal);
213
+ if (request.status === "created") return request;
214
+ if (request.status !== "preparing")
215
+ throw new PrintJobCreateStoppedError(request);
216
+ await pause(interval, signal);
217
+ }
218
+ } catch (error) {
219
+ if (deadline.aborted && !options.signal?.aborted)
220
+ throw new PrintHiveNetworkError("timeout");
221
+ throw error;
222
+ }
223
+ }
224
+ };
225
+
226
+ // 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
+ }
127
236
  function isPath(file) {
128
237
  return !(file instanceof Uint8Array) && !(file instanceof ReadableStream);
129
238
  }
@@ -131,14 +240,35 @@ var prefix = "/v1/partner-production";
131
240
  var PrintHive = class {
132
241
  partnerSources;
133
242
  models;
243
+ printers;
244
+ printJobs;
134
245
  constructor(options) {
135
246
  const transport = new Transport(options);
247
+ this.printJobs = new PrintJobs(transport);
136
248
  const get = (sourceId, signal) => transport.request({
137
- decode: (response) => decode(response, source),
249
+ decode: (response) => decode2(response, source),
138
250
  method: "GET",
139
251
  path: `${prefix}/uploads/${encodeURIComponent(sourceId)}`,
140
252
  signal
141
253
  });
254
+ this.printers = {
255
+ list: (input = {}) => {
256
+ const query = new URLSearchParams();
257
+ if (input.limit !== void 0) query.set("limit", String(input.limit));
258
+ if (input.cursor !== void 0) query.set("cursor", input.cursor);
259
+ return transport.request({
260
+ decode: (response) => decode2(response, printers),
261
+ method: "GET",
262
+ path: "/v1/printers",
263
+ query
264
+ });
265
+ },
266
+ get: (id) => transport.request({
267
+ decode: (response) => decode2(response, printer),
268
+ method: "GET",
269
+ path: `/v1/printers/${encodeURIComponent(id)}`
270
+ })
271
+ };
142
272
  this.partnerSources = {
143
273
  get,
144
274
  async upload(input) {
@@ -172,7 +302,7 @@ var PrintHive = class {
172
302
  if (!Number.isSafeInteger(size) || size < 0)
173
303
  throw new RangeError("size must be a nonnegative safe integer");
174
304
  const source2 = await transport.request({
175
- decode: (response) => decode(response, source),
305
+ decode: (response) => decode2(response, source),
176
306
  method: "POST",
177
307
  path: `${prefix}/uploads`,
178
308
  query,
@@ -198,7 +328,7 @@ var PrintHive = class {
198
328
  }
199
329
  } catch (error) {
200
330
  if (deadline.aborted && !options2.signal?.aborted) {
201
- const { PrintHiveNetworkError: PrintHiveNetworkError2 } = await import("./errors-LHFABGGG.js");
331
+ const { PrintHiveNetworkError: PrintHiveNetworkError2 } = await import("./errors-TJFN2M7S.js");
202
332
  throw new PrintHiveNetworkError2("timeout");
203
333
  }
204
334
  throw error;
@@ -207,7 +337,7 @@ var PrintHive = class {
207
337
  };
208
338
  this.models = {
209
339
  findByExternalId: (externalId) => transport.request({
210
- decode: (response) => decode(response, model),
340
+ decode: (response) => decode2(response, model),
211
341
  method: "GET",
212
342
  path: `${prefix}/models`,
213
343
  query: new URLSearchParams({ externalId })
@@ -218,7 +348,7 @@ var PrintHive = class {
218
348
  const query = new URLSearchParams();
219
349
  if (cursor !== null) query.set("cursor", cursor);
220
350
  const page2 = await transport.request({
221
- decode: (response) => decode(response, page),
351
+ decode: (response) => decode2(response, page),
222
352
  method: "GET",
223
353
  path: `${prefix}/models/${encodeURIComponent(modelId)}/files`,
224
354
  query
@@ -233,5 +363,6 @@ var PrintHive = class {
233
363
  export {
234
364
  PrintHive,
235
365
  PrintHiveApiError,
236
- PrintHiveNetworkError
366
+ PrintHiveNetworkError,
367
+ PrintJobCreateStoppedError
237
368
  };
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@printhive/api",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "private": false,
5
5
  "type": "module",
6
- "description": "Print Hive partner-production REST API client",
6
+ "description": "Print Hive REST API client",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/PrintHive/hive.git",
10
+ "directory": "packages/api-client"
11
+ },
7
12
  "main": "./dist/index.cjs",
8
13
  "module": "./dist/index.js",
9
14
  "types": "./dist/index.d.ts",