import {z} from 'zod' export type CreateApiV1PrintJobsSendsArgs = {body: {submissionId: string, batch: {name: string, modelFileId?: string | undefined} | {batchId: string, supersedes?: Array | undefined} | {unbatched: true, modelFileId?: string | undefined, supersedes?: Array | undefined}, requests: Array<{key: string, body: {[key: string]: unknown}}>}}; export type CreateApiV1PrintJobsSendsOptions = {baseUrl?: string | undefined, apiKeyAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const createApiV1PrintJobsSendsResponse = z.object({sendId: z.string(), submissionId: z.string(), batchId: z.string().nullable(), batchName: z.string().nullable(), replayed: z.boolean(), requests: z.array(z.object({requestId: z.string(), status: z.enum(["preparing", "held", "created", "failed", "cancelled"]), externalId: z.string().nullable(), createdAt: z.string(), plate: z.number().int().nullable().optional(), printerId: z.string().nullable().optional(), name: z.string().nullable().optional(), sourceVersionId: z.string().nullable().optional(), job: z.object({id: z.number(), status: z.string(), model_file_id: z.string().nullable(), printer_id: z.string().nullable(), load_actions: z.array(z.object({actionId: z.string().min(1), sourceSlot: z.number().int().gte(0), kind: z.enum(["load", "swap", "already_loaded"]), filament: z.object({filamentId: z.string().optional(), brand: z.string().nullable().optional(), name: z.string().optional(), colorName: z.string().nullable().optional(), material: z.string().min(1), colorHex: z.string().nullable()}), bay: z.object({id: z.string().min(1), unitLabel: z.string().min(1), label: z.string().min(1), ams_id: z.number().int().gte(0).optional(), slot_id: z.number().int().gte(0).optional()}), current: z.object({material: z.string().nullable(), colorHex: z.string().nullable()}).optional(), text: z.string().min(1)})).nullable().optional(), print_options: z.object({filament_route_state: z.enum(["waiting", "resolved"]).optional(), filament_warnings: z.array(z.string()).optional(), filament_waiting_reasons: z.array(z.object({filamentId: z.string().optional(), brand: z.string().nullable().optional(), name: z.string().optional(), colorName: z.string().nullable().optional(), material: z.string().optional(), colorHex: z.string().optional(), code: z.enum(["filament_not_loaded", "material_route_changed"]), sourceSlot: z.number().int().optional(), color: z.string().nullable().optional(), message: z.string().optional(), messageKind: z.enum(["requirement", "instruction"]).optional(), match: z.union([z.object({kind: z.literal("exact_material"), alternates: z.array(z.string()).optional()}), z.object({kind: z.literal("type_color")}), z.object({kind: z.literal("type_only")})]).optional(), cause: z.enum(["slot_empty", "missing_material", "color_distance", "slot_conflict", "reported_material_mismatch", "material_type_mismatch", "material_unassigned"]).optional(), suggestedTargetSlot: z.object({ams_id: z.number().int(), slot_id: z.number().int()}).optional()})).optional()}).and(z.record(z.string(), z.unknown())).nullable()}).and(z.record(z.string(), z.unknown())).nullable(), requiredActions: z.array(z.union([z.object({item: z.number().int().gte(0), plateNumber: z.number().int().gte(1), hold: z.union([z.object({code: z.literal("external_spool_requires_single_filament"), slots: z.array(z.number().int().gte(1).lte(64))}), z.object({code: z.literal("material_change_requires_qualification"), slots: z.array(z.number().int().gte(1).lte(64))}), z.object({code: z.literal("inspection_review_required"), reason: z.string().min(1)}), z.object({code: z.literal("unmapped_used_slot"), slots: z.array(z.number().int().gte(1).lte(64))}), z.object({code: z.literal("project_source_too_large"), limit: z.object({name: z.literal("projectSourceBytes"), max: z.number().int().gte(1), observed: z.number().int().gte(1)})}), z.object({code: z.literal("project_review_required"), detail: z.string(), changes: z.array(z.object({key: z.string().min(1), sourceValue: z.union([z.string().nullable(), z.array(z.string()), z.number(), z.boolean()]), engineValue: z.union([z.string().nullable(), z.array(z.string()), z.number(), z.boolean()]), slots: z.array(z.number().int().gte(1).lte(64))})).optional(), sourceRelease: z.string().nullable().optional(), engineRelease: z.string().min(1).optional()}), z.object({code: z.literal("preview_mismatch_after_remap"), detail: z.string()})])}).and(z.record(z.string(), z.unknown())), z.object({code: z.string()}).and(z.record(z.string(), z.unknown()))])), warnings: z.array(z.object({code: z.string().min(1)}).and(z.record(z.string(), z.unknown()))).optional(), error: z.record(z.string(), z.unknown()).nullable(), batchId: z.string().nullable().optional(), attempt: z.number().int().gte(0).optional(), retryOf: z.string().nullable().optional(), retriedBy: z.string().nullable().optional(), superseded: z.boolean().optional(), variants: z.array(z.object({targetModelId: z.string(), targetNozzleMm: z.number(), fit: z.string(), status: z.enum(["preparing", "ready", "held", "failed", "cancelled", "discarded"]), representativePrinterId: z.string().nullable(), bound: z.boolean(), warnings: z.array(z.object({code: z.string().min(1)}).and(z.record(z.string(), z.unknown()))).optional(), holds: z.array(z.record(z.string(), z.unknown())).optional(), failure: z.object({code: z.string().optional(), sliceCode: z.string().optional(), message: z.string().optional()}).and(z.record(z.string(), z.unknown())).nullable().optional()})).optional(), filaments: z.array(z.object({filamentId: z.string().optional(), brand: z.string().nullable().optional(), name: z.string().optional(), colorName: z.string().nullable().optional(), material: z.string().optional(), colorHex: z.string().optional(), sourceSlot: z.number().int().gte(0)})).optional(), estimatedSeconds: z.number().int().gte(1).nullable().optional(), createdJobId: z.number().int().nullable().optional(), modelFileId: z.string().nullable().optional()})), superseded: z.array(z.string())}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Send every print request of one project send in one batch * * POST /v1/print-jobs/sends * * Also accepts auth: bearerAuth */ export const createApiV1PrintJobsSends = async (args: CreateApiV1PrintJobsSendsArgs, options?: CreateApiV1PrintJobsSendsOptions) => { const {baseUrl = "https://api.printhiv3d.com", fetch: fetchFn = fetch, apiKeyAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (apiKeyAuth !== undefined) headers.set("x-api-key", apiKeyAuth) const url = `${baseUrl.replace(/\/+$/, '')}/v1/print-jobs/sends${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(createApiV1PrintJobsSendsResponse, await res.json()) };