import {z} from 'zod' export type GetApiProductsHelpDeskTicketsArgs = {view?: ('all' | 'mine' | 'unassigned' | 'team') | undefined, status?: (Array<'open' | 'waiting_on_customer' | 'on_hold' | 'closed'>) | undefined, team_id?: string | undefined, assignee_id?: string | undefined, priority?: (Array<'urgent' | 'high' | 'normal' | 'low'>) | undefined, tag?: string | undefined, q?: string | undefined, requester_id?: string | undefined, sort?: ('last_activity' | 'oldest_waiting') | undefined, cursor?: string | undefined, limit?: number | undefined}; export type GetApiProductsHelpDeskTicketsOptions = {baseUrl?: string | undefined, BearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const helpDeskRequester = z.object({requester_id: z.string(), display_name: z.string().nullable(), email: z.string(), assurance: z.enum(["identity", "email_pin"])}).nullable(); export const helpDeskPresenceEntry = z.object({user_id: z.string(), state: z.enum(["viewing", "replying"])}); export const helpDeskQueueRow = z.object({ticket_id: z.string(), number: z.number().int(), status: z.enum(["open", "waiting_on_customer", "on_hold", "closed"]), close_reason: z.enum(["resolved", "duplicate", "spam", "null"]).nullable(), hold_until: z.number().int().nullable(), priority: z.enum(["urgent", "high", "normal", "low"]), team_id: z.string().nullable(), assignee_id: z.string().nullable(), requester_id: z.string(), subject: z.string(), preview: z.string(), tags: z.array(z.string()), created_at: z.number().int(), last_activity_at: z.number().int().nullable(), last_customer_message_at: z.number().int().nullable(), first_operator_reply_at: z.number().int().nullable(), last_operator_reply_at: z.number().int().nullable(), merged_into: z.string().nullable(), merged_into_number: z.number().int().nullable(), muted: z.boolean(), awaiting_first_response: z.boolean(), version: z.number().int(), requester: helpDeskRequester, presence: z.array(helpDeskPresenceEntry).optional()}); export const helpDeskQueuePage = z.object({items: z.array(helpDeskQueueRow), next_cursor: z.string().nullable(), partial: z.boolean().optional()}); export const responseMeta = z.object({api_version: z.string().optional(), request_id: z.string().optional(), response_ms: z.number().int().optional(), timestamp: z.number().int().optional(), pools: z.object({}).optional(), billing: z.object({past_due: z.boolean().optional()}).optional(), quota: z.object({limit: z.number().int().optional(), used: z.number().int().optional(), remaining: z.number().int().optional(), resets_at: z.number().int().optional()}).optional()}); export const getApiProductsHelpDeskTicketsResponse = z.object({data: helpDeskQueuePage, meta: responseMeta.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 }; /** * List the queue * * GET /products/help-desk/tickets */ export const getApiProductsHelpDeskTickets = async (args: GetApiProductsHelpDeskTicketsArgs, options?: GetApiProductsHelpDeskTicketsOptions) => { const {baseUrl = "https://api.sparkvault.com/v1", fetch: fetchFn = fetch, BearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.view != null) query.append("view", String(args.view)) for (const item of args.status ?? []) query.append("status", String(item)) if (args.team_id != null) query.append("team_id", String(args.team_id)) if (args.assignee_id != null) query.append("assignee_id", String(args.assignee_id)) for (const item of args.priority ?? []) query.append("priority", String(item)) if (args.tag != null) query.append("tag", String(args.tag)) if (args.q != null) query.append("q", String(args.q)) if (args.requester_id != null) query.append("requester_id", String(args.requester_id)) if (args.sort != null) query.append("sort", String(args.sort)) if (args.cursor != null) query.append("cursor", String(args.cursor)) if (args.limit != null) query.append("limit", String(args.limit)) if (BearerAuth !== undefined) headers.set('authorization', `Bearer ${BearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/products/help-desk/tickets${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getApiProductsHelpDeskTicketsResponse, await res.json()) };