import {z} from 'zod' export type CreateApiPrintJobsArgs = {body: {contact_email: string, costs?: ({line_item_costs?: ({cost_excl_discounts: string, discounts: Array<{amount: string, description: string}>, quantity: number, tax_rate: string, total_cost_excl_discounts: string, total_cost_excl_tax: string, total_cost_incl_tax: string, total_tax: string, unit_tier_cost?: string | undefined}) | undefined, shipping_cost?: ({tax_rate?: string | undefined, total_cost_excl_tax?: string | undefined, total_cost_incl_tax?: string | undefined, total_tax?: string | undefined}) | undefined, total_cost_excl_tax?: string | undefined, total_cost_incl_tax?: string | undefined, total_tax?: string | undefined}) | undefined, estimated_shipping_dates?: ({arrival_max?: string | undefined, arrival_min?: string | undefined, dispatch_max?: string | undefined, dispatch_min?: string | undefined}) | undefined, external_id?: string | undefined, id: number, line_items: Array<{cover?: ({source_md5_sum?: string | undefined, source_url: string} | string) | undefined, external_id?: string | undefined, id: number, interior?: ({source_md5_sum?: string | undefined, source_url: string} | string) | undefined, page_count?: number | undefined, pod_package_id?: string | undefined, printable_id?: string | undefined, printable_normalization?: ({cover: {job_id?: number | undefined, normalized_file?: ({file_id?: number | undefined, filename?: string | undefined}) | undefined, source_md5_sum?: string | undefined, source_url: string}, interior: {job_id?: number | undefined, normalized_file?: ({file_id?: number | undefined, filename?: string | undefined}) | undefined, source_md5_sum?: string | undefined, source_url: string}}) | undefined, quantity: number, status: {messages?: ({delay?: string | undefined, error?: string | undefined, info?: string | undefined, printable_normalization?: ({cover?: Array | undefined, interior?: Array | undefined}) | undefined, timestamp?: string | undefined, url?: (string | Array) | undefined}) | undefined, name: 'CREATED' | 'ACCEPTED' | 'REJECTED' | 'IN_PRODUCTION' | 'ERROR' | 'SHIPPED'}, title?: string | undefined, tracking_id?: string | undefined, tracking_urls?: Array | undefined}>, order_id?: string | undefined, production_delay?: number | undefined, production_due_time?: string | undefined, shipping_address: {city: string, country_code: string, email: string, is_business?: boolean | undefined, name: string, organization?: string | undefined, phone_number: string, postcode: string, state_code?: string | undefined, street1: string, street2?: string | undefined, title?: ('MR' | 'MISS' | 'MRS' | 'MS' | 'DR') | undefined, recipient_tax_id?: string | undefined}, shipping_level: 'MAIL' | 'PRIORITY_MAIL' | 'GROUND_HD' | 'GROUND_BUS' | 'GROUND' | 'EXPEDITED' | 'EXPRESS', tax_country?: string | undefined}}; export type CreateApiPrintJobsOptions = {baseUrl?: string | undefined, oauth2?: string | undefined, fetch?: typeof fetch | undefined}; export const createApiPrintJobsResponse = z.object({contact_email: z.string(), costs: z.object({line_item_costs: z.object({cost_excl_discounts: z.string(), discounts: z.array(z.object({amount: z.string(), description: z.string()})), quantity: z.number(), tax_rate: z.string(), total_cost_excl_discounts: z.string(), total_cost_excl_tax: z.string(), total_cost_incl_tax: z.string(), total_tax: z.string(), unit_tier_cost: z.string().optional()}).optional(), shipping_cost: z.object({tax_rate: z.string().optional(), total_cost_excl_tax: z.string().optional(), total_cost_incl_tax: z.string().optional(), total_tax: z.string().optional()}).optional(), total_cost_excl_tax: z.string().optional(), total_cost_incl_tax: z.string().optional(), total_tax: z.string().optional()}).optional(), estimated_shipping_dates: z.object({arrival_max: z.string().optional(), arrival_min: z.string().optional(), dispatch_max: z.string().optional(), dispatch_min: z.string().optional()}).optional(), external_id: z.string().optional(), id: z.number(), line_items: z.array(z.object({cover: z.union([z.object({source_md5_sum: z.string().optional(), source_url: z.string()}), z.string()]).optional(), external_id: z.string().optional(), id: z.number(), interior: z.union([z.object({source_md5_sum: z.string().optional(), source_url: z.string()}), z.string()]).optional(), page_count: z.number().optional(), pod_package_id: z.string().max(100).optional(), printable_id: z.string().optional(), printable_normalization: z.object({cover: z.object({job_id: z.number().optional(), normalized_file: z.object({file_id: z.number().optional(), filename: z.string().optional()}).optional(), source_md5_sum: z.string().optional(), source_url: z.string()}), interior: z.object({job_id: z.number().optional(), normalized_file: z.object({file_id: z.number().optional(), filename: z.string().optional()}).optional(), source_md5_sum: z.string().optional(), source_url: z.string()})}).optional(), quantity: z.number(), status: z.object({messages: z.object({delay: z.string().max(64).optional(), error: z.string().optional(), info: z.string().optional(), printable_normalization: z.object({cover: z.array(z.string()).optional(), interior: z.array(z.string()).optional()}).optional(), timestamp: z.string().max(64).optional(), url: z.union([z.string(), z.array(z.string())]).optional()}).optional(), name: z.enum(["CREATED", "ACCEPTED", "REJECTED", "IN_PRODUCTION", "ERROR", "SHIPPED"])}), title: z.string().max(255).optional(), tracking_id: z.string().optional(), tracking_urls: z.array(z.string()).optional()})), order_id: z.string().optional(), production_delay: z.number().int().gte(60).lte(2880).optional(), production_due_time: z.string().optional(), shipping_address: z.object({city: z.string(), country_code: z.string().min(2).max(2), email: z.string(), is_business: z.boolean().optional(), name: z.string(), organization: z.string().optional(), phone_number: z.string().max(20), postcode: z.string().max(64), state_code: z.string().optional(), street1: z.string(), street2: z.string().optional(), title: z.enum(["MR", "MISS", "MRS", "MS", "DR"]).optional(), warnings: z.array(z.object({type: z.string().optional(), code: z.string().optional(), path: z.string().optional(), message: z.string().optional()})).optional(), suggested_address: z.object({country_code: z.string().optional(), state_code: z.string().optional(), postcode: z.string().optional(), city: z.string().optional(), street1: z.string().optional(), street2: z.string().optional()}).optional()}), shipping_level: z.enum(["MAIL", "PRIORITY_MAIL", "GROUND_HD", "GROUND_BUS", "GROUND", "EXPEDITED", "EXPRESS"]), tax_country: z.string().max(2).optional()}); 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 }; /** * Create a new Print-Job * * POST /print-jobs/ */ export const createApiPrintJobs = async (args: CreateApiPrintJobsArgs, options?: CreateApiPrintJobsOptions) => { const {baseUrl = "https://api.lulu.com", fetch: fetchFn = fetch, oauth2} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (oauth2 !== undefined) headers.set('authorization', `Bearer ${oauth2}`) const url = `${baseUrl.replace(/\/+$/, '')}/print-jobs/${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(createApiPrintJobsResponse, await res.json()) };