@printhive/react 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/dist/chunk-RY4P4TFQ.js +28 -0
- package/dist/chunk-RY4P4TFQ.js.map +1 -0
- package/dist/index.cjs +918 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +62 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.js +901 -0
- package/dist/index.js.map +1 -0
- package/dist/server.cjs +305 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +11 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +262 -0
- package/dist/server.js.map +1 -0
- package/dist/styles.css +482 -0
- package/package.json +80 -4
- package/README.md +0 -3
package/dist/server.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FilamentManagementError,
|
|
3
|
+
requirePrinterLayout
|
|
4
|
+
} from "./chunk-RY4P4TFQ.js";
|
|
5
|
+
|
|
6
|
+
// src/server.ts
|
|
7
|
+
import {
|
|
8
|
+
PrintHiveApiError
|
|
9
|
+
} from "@printhive/api";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
var slotInput = z.object({ slotId: z.string().min(1) }).strict();
|
|
12
|
+
var assignInput = slotInput.extend({ materialId: z.string().min(1) });
|
|
13
|
+
var clearInput = slotInput.extend({
|
|
14
|
+
expectedVersion: z.object({ id: z.string().min(1), updatedAt: z.string().nullable() }).strict()
|
|
15
|
+
});
|
|
16
|
+
var routeSchema = z.object({
|
|
17
|
+
printerId: z.string().uuid(),
|
|
18
|
+
action: z.enum(["read", "catalog", "assign", "clear", "refresh-rfid"])
|
|
19
|
+
});
|
|
20
|
+
function slots(layout) {
|
|
21
|
+
return [
|
|
22
|
+
...layout.nozzles.flatMap(
|
|
23
|
+
(nozzle) => nozzle.sources.flatMap((source) => source.slots)
|
|
24
|
+
),
|
|
25
|
+
...layout.unboundSources.flatMap((source) => source.slots),
|
|
26
|
+
...layout.unmappedAssignments
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
function readOnly(layout) {
|
|
30
|
+
const copy = structuredClone(layout);
|
|
31
|
+
const unavailable = {
|
|
32
|
+
kind: "unavailable",
|
|
33
|
+
code: "permission_required",
|
|
34
|
+
message: "Your connection has read-only access."
|
|
35
|
+
};
|
|
36
|
+
for (const slot of slots(copy)) {
|
|
37
|
+
slot.capabilities = {
|
|
38
|
+
assign: unavailable,
|
|
39
|
+
clearAssignment: unavailable,
|
|
40
|
+
writePrinterMetadata: unavailable,
|
|
41
|
+
refreshRfid: unavailable
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return copy;
|
|
45
|
+
}
|
|
46
|
+
function target(layout, slotId, action) {
|
|
47
|
+
const slot = slots(layout).find((candidate) => candidate.id === slotId);
|
|
48
|
+
if (!slot)
|
|
49
|
+
throw new FilamentManagementError(
|
|
50
|
+
"This slot is no longer available. Refresh the printer.",
|
|
51
|
+
{ code: "slot_not_present", status: 404 }
|
|
52
|
+
);
|
|
53
|
+
const capability = slot.capabilities[action];
|
|
54
|
+
if (capability.kind === "unavailable") {
|
|
55
|
+
throw new FilamentManagementError(capability.message, {
|
|
56
|
+
code: capability.code,
|
|
57
|
+
status: capability.code === "permission_required" ? 403 : 409
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return slot;
|
|
61
|
+
}
|
|
62
|
+
function route(request, basePath) {
|
|
63
|
+
const prefix = `${basePath}/printers/`;
|
|
64
|
+
const path = new URL(request.url).pathname;
|
|
65
|
+
if (!path.startsWith(prefix)) return null;
|
|
66
|
+
const [id, resource, suffix, ...extra] = path.slice(prefix.length).split("/");
|
|
67
|
+
if (resource !== "filaments" || extra.length || !id) return null;
|
|
68
|
+
const action = suffix || "read";
|
|
69
|
+
let printerId;
|
|
70
|
+
try {
|
|
71
|
+
printerId = decodeURIComponent(id);
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const parsed = routeSchema.safeParse({ printerId, action });
|
|
76
|
+
if (!parsed.success) return null;
|
|
77
|
+
const expectedMethod = action === "read" || action === "catalog" ? "GET" : "POST";
|
|
78
|
+
if (request.method !== expectedMethod)
|
|
79
|
+
throw new FilamentManagementError("This request method is not supported.", {
|
|
80
|
+
code: "method_not_allowed",
|
|
81
|
+
status: 405
|
|
82
|
+
});
|
|
83
|
+
if (expectedMethod === "POST" && request.headers.get("content-type")?.split(";")[0]?.trim() !== "application/json") {
|
|
84
|
+
throw new FilamentManagementError("Send filament changes as JSON.", {
|
|
85
|
+
code: "invalid_request",
|
|
86
|
+
status: 415
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return parsed.data;
|
|
90
|
+
}
|
|
91
|
+
async function body(request, schema) {
|
|
92
|
+
const value = await request.json().catch(() => null);
|
|
93
|
+
const result = schema.safeParse(value);
|
|
94
|
+
if (!result.success)
|
|
95
|
+
throw new FilamentManagementError("The filament request is invalid.", {
|
|
96
|
+
code: "invalid_request",
|
|
97
|
+
status: 400
|
|
98
|
+
});
|
|
99
|
+
return result.data;
|
|
100
|
+
}
|
|
101
|
+
var messages = /* @__PURE__ */ new Map([
|
|
102
|
+
[
|
|
103
|
+
"assignment_changed",
|
|
104
|
+
"This assignment changed elsewhere. Refresh before clearing it."
|
|
105
|
+
],
|
|
106
|
+
["printer_busy", "The printer is busy. Try again when it is available."],
|
|
107
|
+
["printer_not_found", "This printer is not available to your connection."],
|
|
108
|
+
[
|
|
109
|
+
"slot_not_present",
|
|
110
|
+
"This slot is no longer available. Refresh the printer."
|
|
111
|
+
],
|
|
112
|
+
[
|
|
113
|
+
"filament_at_extruder",
|
|
114
|
+
"RFID cannot be refreshed while filament is at the extruder."
|
|
115
|
+
],
|
|
116
|
+
[
|
|
117
|
+
"filament_state_unknown",
|
|
118
|
+
"The filament state is unknown. Refresh the printer before reading RFID."
|
|
119
|
+
],
|
|
120
|
+
["rfid_protocol_unsupported", "This printer does not support RFID refresh."],
|
|
121
|
+
["external_rfid_unsupported", "External spools do not support RFID refresh."],
|
|
122
|
+
[
|
|
123
|
+
"printer_metadata_unsupported",
|
|
124
|
+
"This printer does not support writing filament metadata."
|
|
125
|
+
]
|
|
126
|
+
]);
|
|
127
|
+
function failure(error) {
|
|
128
|
+
if (error instanceof FilamentManagementError) {
|
|
129
|
+
return Response.json(
|
|
130
|
+
{ error: error.code, message: error.message },
|
|
131
|
+
{ status: error.status ?? 500 }
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
if (error instanceof PrintHiveApiError) {
|
|
135
|
+
return Response.json(
|
|
136
|
+
{
|
|
137
|
+
error: messages.has(error.code) ? error.code : "request_failed",
|
|
138
|
+
message: messages.get(error.code) ?? "The filament request could not be completed. Try again."
|
|
139
|
+
},
|
|
140
|
+
{ status: error.status }
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
return Response.json(
|
|
144
|
+
{
|
|
145
|
+
error: "service_unavailable",
|
|
146
|
+
message: "The filament service is unavailable. Try again."
|
|
147
|
+
},
|
|
148
|
+
{ status: 503 }
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
async function operate(client, request, printerId, action, access) {
|
|
152
|
+
if (action === "catalog") {
|
|
153
|
+
const query = new URL(request.url).searchParams.get("q") ?? "";
|
|
154
|
+
return client.filaments.search({
|
|
155
|
+
query,
|
|
156
|
+
limit: 20,
|
|
157
|
+
signal: request.signal
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (action === "read") {
|
|
161
|
+
const layout2 = requirePrinterLayout(
|
|
162
|
+
await client.printers.materialSlots.layout(printerId, request.signal),
|
|
163
|
+
printerId
|
|
164
|
+
);
|
|
165
|
+
return access === "read" ? readOnly(layout2) : layout2;
|
|
166
|
+
}
|
|
167
|
+
if (action === "assign") {
|
|
168
|
+
const input2 = await body(request, assignInput);
|
|
169
|
+
const layout2 = requirePrinterLayout(
|
|
170
|
+
await client.printers.materialSlots.layout(printerId, request.signal),
|
|
171
|
+
printerId
|
|
172
|
+
);
|
|
173
|
+
const slot2 = target(layout2, input2.slotId, "assign");
|
|
174
|
+
return client.printers.materialSlots.assign(
|
|
175
|
+
printerId,
|
|
176
|
+
{
|
|
177
|
+
syncPolicy: "automatic",
|
|
178
|
+
slots: [{ position: slot2.position, materialId: input2.materialId }]
|
|
179
|
+
},
|
|
180
|
+
request.signal
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
if (action === "clear") {
|
|
184
|
+
const input2 = await body(request, clearInput);
|
|
185
|
+
const layout2 = requirePrinterLayout(
|
|
186
|
+
await client.printers.materialSlots.layout(printerId, request.signal),
|
|
187
|
+
printerId
|
|
188
|
+
);
|
|
189
|
+
const slot2 = target(layout2, input2.slotId, "clearAssignment");
|
|
190
|
+
if (!slot2.assignment?.version) {
|
|
191
|
+
throw new FilamentManagementError(
|
|
192
|
+
"This assignment changed elsewhere. Refresh before clearing it.",
|
|
193
|
+
{ code: "assignment_changed", status: 409 }
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
return client.printers.materialSlots.clearAssignments(
|
|
197
|
+
printerId,
|
|
198
|
+
[slot2.position],
|
|
199
|
+
{ expectedVersion: input2.expectedVersion, signal: request.signal }
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
const input = await body(request, slotInput);
|
|
203
|
+
const layout = requirePrinterLayout(
|
|
204
|
+
await client.printers.materialSlots.layout(printerId, request.signal),
|
|
205
|
+
printerId
|
|
206
|
+
);
|
|
207
|
+
const slot = target(layout, input.slotId, "refreshRfid");
|
|
208
|
+
return client.printers.materialSlots.refreshRfid(
|
|
209
|
+
printerId,
|
|
210
|
+
slot.position,
|
|
211
|
+
request.signal
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
function createFilamentManagementHandler(options) {
|
|
215
|
+
const basePath = (options.basePath ?? "/api/printhive").replace(/\/+$/, "");
|
|
216
|
+
if (basePath && !basePath.startsWith("/"))
|
|
217
|
+
throw new TypeError("basePath must start with /");
|
|
218
|
+
return async (request) => {
|
|
219
|
+
try {
|
|
220
|
+
const parsed = route(request, basePath);
|
|
221
|
+
if (!parsed)
|
|
222
|
+
return Response.json(
|
|
223
|
+
{
|
|
224
|
+
error: "not_found",
|
|
225
|
+
message: "This filament route does not exist."
|
|
226
|
+
},
|
|
227
|
+
{ status: 404 }
|
|
228
|
+
);
|
|
229
|
+
const access = await options.authorize(request, parsed.printerId);
|
|
230
|
+
if (access !== "read" && access !== "control" || access !== "control" && parsed.action !== "read" && parsed.action !== "catalog") {
|
|
231
|
+
return Response.json(
|
|
232
|
+
{
|
|
233
|
+
error: "permission_required",
|
|
234
|
+
message: "You do not have access to this filament operation."
|
|
235
|
+
},
|
|
236
|
+
{ status: 403 }
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
return Response.json(
|
|
240
|
+
await operate(
|
|
241
|
+
options.client,
|
|
242
|
+
request,
|
|
243
|
+
parsed.printerId,
|
|
244
|
+
parsed.action,
|
|
245
|
+
access
|
|
246
|
+
),
|
|
247
|
+
{ headers: { "cache-control": "no-store" } }
|
|
248
|
+
);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
return failure(
|
|
251
|
+
error instanceof FilamentManagementError || error instanceof PrintHiveApiError ? error : new FilamentManagementError(
|
|
252
|
+
"The filament service is unavailable. Try again.",
|
|
253
|
+
{ code: "service_unavailable", status: 503 }
|
|
254
|
+
)
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
export {
|
|
260
|
+
createFilamentManagementHandler
|
|
261
|
+
};
|
|
262
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import {\n PrintHiveApiError,\n type PrintHive,\n type PrinterMaterialLayout,\n type AssignFilamentsResult,\n type ClearFilamentAssignmentsResult,\n type RefreshMaterialSlotRfidResult,\n type FilamentSearchPage,\n} from \"@printhive/api\";\nimport { z } from \"zod\";\nimport { FilamentManagementError } from \"./errors.js\";\nimport { requirePrinterLayout } from \"./layout-identity.js\";\nimport type { FilamentLayoutSlot } from \"./types.js\";\n\ntype FilamentAccess = \"read\" | \"control\" | null;\ntype Action = \"read\" | \"catalog\" | \"assign\" | \"clear\" | \"refresh-rfid\";\ntype FilamentResponse =\n | PrinterMaterialLayout\n | AssignFilamentsResult\n | ClearFilamentAssignmentsResult\n | RefreshMaterialSlotRfidResult\n | FilamentSearchPage;\n\nexport interface FilamentManagementHandlerOptions {\n client: PrintHive;\n authorize: (\n request: Request,\n printerId: string\n ) => FilamentAccess | Promise<FilamentAccess>;\n basePath?: string;\n}\n\nconst slotInput = z.object({ slotId: z.string().min(1) }).strict();\nconst assignInput = slotInput.extend({ materialId: z.string().min(1) });\nconst clearInput = slotInput.extend({\n expectedVersion: z\n .object({ id: z.string().min(1), updatedAt: z.string().nullable() })\n .strict(),\n});\nconst routeSchema = z.object({\n printerId: z.string().uuid(),\n action: z.enum([\"read\", \"catalog\", \"assign\", \"clear\", \"refresh-rfid\"]),\n});\n\nfunction slots(layout: PrinterMaterialLayout): FilamentLayoutSlot[] {\n return [\n ...layout.nozzles.flatMap((nozzle) =>\n nozzle.sources.flatMap((source) => source.slots)\n ),\n ...layout.unboundSources.flatMap((source) => source.slots),\n ...layout.unmappedAssignments,\n ];\n}\n\nfunction readOnly(layout: PrinterMaterialLayout): PrinterMaterialLayout {\n const copy = structuredClone(layout);\n const unavailable: FilamentLayoutSlot[\"capabilities\"][\"assign\"] = {\n kind: \"unavailable\",\n code: \"permission_required\",\n message: \"Your connection has read-only access.\",\n };\n for (const slot of slots(copy)) {\n slot.capabilities = {\n assign: unavailable,\n clearAssignment: unavailable,\n writePrinterMetadata: unavailable,\n refreshRfid: unavailable,\n };\n }\n return copy;\n}\n\nfunction target(\n layout: PrinterMaterialLayout,\n slotId: string,\n action: keyof FilamentLayoutSlot[\"capabilities\"]\n): FilamentLayoutSlot {\n const slot = slots(layout).find((candidate) => candidate.id === slotId);\n if (!slot)\n throw new FilamentManagementError(\n \"This slot is no longer available. Refresh the printer.\",\n { code: \"slot_not_present\", status: 404 }\n );\n const capability = slot.capabilities[action];\n if (capability.kind === \"unavailable\") {\n throw new FilamentManagementError(capability.message, {\n code: capability.code,\n status: capability.code === \"permission_required\" ? 403 : 409,\n });\n }\n return slot;\n}\n\nfunction route(request: Request, basePath: string) {\n const prefix = `${basePath}/printers/`;\n const path = new URL(request.url).pathname;\n if (!path.startsWith(prefix)) return null;\n const [id, resource, suffix, ...extra] = path.slice(prefix.length).split(\"/\");\n if (resource !== \"filaments\" || extra.length || !id) return null;\n const action = suffix || \"read\";\n let printerId: string;\n try {\n printerId = decodeURIComponent(id);\n } catch {\n return null;\n }\n const parsed = routeSchema.safeParse({ printerId, action });\n if (!parsed.success) return null;\n const expectedMethod =\n action === \"read\" || action === \"catalog\" ? \"GET\" : \"POST\";\n if (request.method !== expectedMethod)\n throw new FilamentManagementError(\"This request method is not supported.\", {\n code: \"method_not_allowed\",\n status: 405,\n });\n if (\n expectedMethod === \"POST\" &&\n request.headers.get(\"content-type\")?.split(\";\")[0]?.trim() !==\n \"application/json\"\n ) {\n throw new FilamentManagementError(\"Send filament changes as JSON.\", {\n code: \"invalid_request\",\n status: 415,\n });\n }\n return parsed.data;\n}\n\nasync function body<T>(request: Request, schema: z.ZodType<T>): Promise<T> {\n const value: unknown = await request.json().catch(() => null);\n const result = schema.safeParse(value);\n if (!result.success)\n throw new FilamentManagementError(\"The filament request is invalid.\", {\n code: \"invalid_request\",\n status: 400,\n });\n return result.data;\n}\n\nconst messages = new Map([\n [\n \"assignment_changed\",\n \"This assignment changed elsewhere. Refresh before clearing it.\",\n ],\n [\"printer_busy\", \"The printer is busy. Try again when it is available.\"],\n [\"printer_not_found\", \"This printer is not available to your connection.\"],\n [\n \"slot_not_present\",\n \"This slot is no longer available. Refresh the printer.\",\n ],\n [\n \"filament_at_extruder\",\n \"RFID cannot be refreshed while filament is at the extruder.\",\n ],\n [\n \"filament_state_unknown\",\n \"The filament state is unknown. Refresh the printer before reading RFID.\",\n ],\n [\"rfid_protocol_unsupported\", \"This printer does not support RFID refresh.\"],\n [\"external_rfid_unsupported\", \"External spools do not support RFID refresh.\"],\n [\n \"printer_metadata_unsupported\",\n \"This printer does not support writing filament metadata.\",\n ],\n]);\n\nfunction failure(error: FilamentManagementError | PrintHiveApiError): Response {\n if (error instanceof FilamentManagementError) {\n return Response.json(\n { error: error.code, message: error.message },\n { status: error.status ?? 500 }\n );\n }\n if (error instanceof PrintHiveApiError) {\n return Response.json(\n {\n error: messages.has(error.code) ? error.code : \"request_failed\",\n message:\n messages.get(error.code) ??\n \"The filament request could not be completed. Try again.\",\n },\n { status: error.status }\n );\n }\n return Response.json(\n {\n error: \"service_unavailable\",\n message: \"The filament service is unavailable. Try again.\",\n },\n { status: 503 }\n );\n}\n\nasync function operate(\n client: PrintHive,\n request: Request,\n printerId: string,\n action: Action,\n access: Exclude<FilamentAccess, null>\n): Promise<FilamentResponse> {\n if (action === \"catalog\") {\n const query = new URL(request.url).searchParams.get(\"q\") ?? \"\";\n return client.filaments.search({\n query,\n limit: 20,\n signal: request.signal,\n });\n }\n if (action === \"read\") {\n const layout = requirePrinterLayout(\n await client.printers.materialSlots.layout(printerId, request.signal),\n printerId\n );\n return access === \"read\" ? readOnly(layout) : layout;\n }\n if (action === \"assign\") {\n const input = await body(request, assignInput);\n const layout = requirePrinterLayout(\n await client.printers.materialSlots.layout(printerId, request.signal),\n printerId\n );\n const slot = target(layout, input.slotId, \"assign\");\n return client.printers.materialSlots.assign(\n printerId,\n {\n syncPolicy: \"automatic\",\n slots: [{ position: slot.position, materialId: input.materialId }],\n },\n request.signal\n );\n }\n if (action === \"clear\") {\n const input = await body(request, clearInput);\n const layout = requirePrinterLayout(\n await client.printers.materialSlots.layout(printerId, request.signal),\n printerId\n );\n const slot = target(layout, input.slotId, \"clearAssignment\");\n if (!slot.assignment?.version) {\n throw new FilamentManagementError(\n \"This assignment changed elsewhere. Refresh before clearing it.\",\n { code: \"assignment_changed\", status: 409 }\n );\n }\n return client.printers.materialSlots.clearAssignments(\n printerId,\n [slot.position],\n { expectedVersion: input.expectedVersion, signal: request.signal }\n );\n }\n const input = await body(request, slotInput);\n const layout = requirePrinterLayout(\n await client.printers.materialSlots.layout(printerId, request.signal),\n printerId\n );\n const slot = target(layout, input.slotId, \"refreshRfid\");\n return client.printers.materialSlots.refreshRfid(\n printerId,\n slot.position,\n request.signal\n );\n}\n\nexport function createFilamentManagementHandler(\n options: FilamentManagementHandlerOptions\n): (request: Request) => Promise<Response> {\n const basePath = (options.basePath ?? \"/api/printhive\").replace(/\\/+$/, \"\");\n if (basePath && !basePath.startsWith(\"/\"))\n throw new TypeError(\"basePath must start with /\");\n return async (request) => {\n try {\n const parsed = route(request, basePath);\n if (!parsed)\n return Response.json(\n {\n error: \"not_found\",\n message: \"This filament route does not exist.\",\n },\n { status: 404 }\n );\n const access = await options.authorize(request, parsed.printerId);\n if (\n (access !== \"read\" && access !== \"control\") ||\n (access !== \"control\" &&\n parsed.action !== \"read\" &&\n parsed.action !== \"catalog\")\n ) {\n return Response.json(\n {\n error: \"permission_required\",\n message: \"You do not have access to this filament operation.\",\n },\n { status: 403 }\n );\n }\n return Response.json(\n await operate(\n options.client,\n request,\n parsed.printerId,\n parsed.action,\n access\n ),\n { headers: { \"cache-control\": \"no-store\" } }\n );\n } catch (error) {\n return failure(\n error instanceof FilamentManagementError ||\n error instanceof PrintHiveApiError\n ? error\n : new FilamentManagementError(\n \"The filament service is unavailable. Try again.\",\n { code: \"service_unavailable\", status: 503 }\n )\n );\n }\n };\n}\n"],"mappings":"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","names":["layout","input","slot"]}
|