import {z} from 'zod' export type MetricCardStatusEnum = 'published' | 'deprecated'; export type MetricCardIncludeEnum = 'deprecated'; export type GetApiApiMetricCardsArgs = {category?: string | undefined, status?: MetricCardStatusEnum | undefined, q?: string | undefined, include?: MetricCardIncludeEnum | undefined}; export type GetApiApiMetricCardsOptions = {baseUrl?: string | undefined, basicAuth?: {username: string, password: string} | undefined, fetch?: typeof fetch | undefined}; export const metricCardSlugEnum = z.enum(["abandoned-calls", "accuracy", "achievement-rate", "agents-offline", "agents-online", "ai-agent-automation-rate", "ai-agent-average-csat", "ai-agent-closed-tickets", "all-used-tags-all", "all-used-tags-all-created", "all-used-values", "all-used-values-created", "article-views", "assigned-open-tickets", "automated-interactions", "available-time", "average-csat", "average-discount-amount", "average-first-response-time", "average-human-response-time-after-ai-handoff", "average-order-value", "average-resolution-time", "average-survey-score", "average-talk-time", "average-ticket-handle-time", "average-wait-time", "brand-voice", "buy-through-rate", "call-wrap-up-time", "callback-requests", "calls-in-queue", "calls-with-achieved-slas", "calls-with-breached-slas", "cancelled-calls", "click-through-rate", "closed-tickets", "closed-tickets-per-hour", "comment-highlights", "communication-skills", "contribution-to-total-sales", "conversion-rate", "cost-saved", "coverage-rate", "created-tickets", "decrease-in-frt", "decrease-in-resolution-time", "discount-codes-applied", "discount-usage", "discounts-offered", "efficiency", "first-response-time", "handover-interactions", "human-response-time-after-ai-handoff", "inbound-answered", "inbound-answered-per-agent", "inbound-calls", "inbound-declined", "inbound-transferred", "internal-compliance", "language-proficiency", "live-messages-sent", "live-online-status", "live-open-tickets", "live-tickets-closed", "live-tickets-created", "live-tickets-replied", "macro-share-of-total", "macro-total-tickets", "macro-trend", "median-purchase-time", "median-response-time", "messages-per-ticket", "messages-received", "messages-sent", "messages-sent-per-hour", "messages-sent-per-macro", "missed-calls", "no-result-searches", "no-search-results-search-count", "on-a-call-time", "one-touch-tickets", "online-time", "open-tickets", "orders-influenced", "outbound-calls", "overall-automation-rate", "percent-abandoned-calls", "percent-callback-requests", "percent-cancelled-calls", "percent-missed-calls", "percent-one-touch-tickets", "percent-sla-achievement-rate", "percent-zero-touch-tickets", "percentage-of-closed-tickets", "percentage-of-created-tickets", "performance-per-article-views", "product-recommendations", "resolution-completeness", "resolution-time", "response-rate", "revenue-influenced", "revenue-per-interaction", "reviewed-tickets", "satisfaction-score", "search-results", "search-terms-with-results-articles-clicked", "search-terms-with-results-click-through-rate", "search-terms-with-results-search-count", "searches", "success-rate", "surveys-answered", "surveys-sent", "ticket-attribute-intents", "ticket-attribute-share-of-total", "ticket-attribute-tickets", "ticket-attribute-trend", "ticket-handle-time-per-agent", "tickets-replied", "tickets-replied-per-hour", "tickets-with-achieved-slas", "tickets-with-breached-slas", "time-saved-by-agent", "top-performer-frt", "top-performers-closed-tickets", "top-performers-csat", "top-performers-resolution-time", "top-used-tags-all", "top-used-tags-all-created", "top-used-tags-all-created-trend", "top-used-tags-all-trend", "top-used-values", "top-used-values-created", "top-used-values-created-trend", "top-used-values-trend", "total-calls", "total-sales", "total-time", "unanswered-calls", "unassigned-open-tickets", "unavailable-time", "wait-time-per-call", "zero-touch-tickets"]); export const metricCardStatusEnum = z.enum(["published", "deprecated"]); export const metricCardPublic = z.object({definition: z.string(), formula: z.string(), computation_logic: z.array(z.string())}); export const metricCardApiFilter = z.object({member: z.string(), values: z.array(z.string())}); export const metricCardApiMapping = z.object({scope: z.string(), measures: z.array(z.string()).optional(), dimensions: z.array(z.string()).optional(), filters: z.array(metricCardApiFilter).optional()}); export const metricCardRef = z.object({slug: z.string(), url: z.string()}); export const metricCard = z.object({slug: metricCardSlugEnum, category: z.string(), title: z.string(), status: metricCardStatusEnum, definition_revised_at: z.string(), public: metricCardPublic, api: metricCardApiMapping.optional(), aliases: z.array(z.string()), related: z.array(metricCardRef), replaces: z.array(metricCardRef), used_in_reports: z.array(z.string()), used_in_reports_links: z.array(z.string()).optional()}); export const metricCardList = z.object({data: z.array(metricCard)}); 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 }; /** * Search metric cards * * GET /api/metric-cards */ export const getApiApiMetricCards = async (args: GetApiApiMetricCardsArgs, options?: GetApiApiMetricCardsOptions) => { const {baseUrl = "https://your-domain.gorgias.com", fetch: fetchFn = fetch, basicAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.category != null) query.append("category", String(args.category)) if (args.status != null) query.append("status", String(args.status)) if (args.q != null) query.append("q", String(args.q)) if (args.include != null) query.append("include", String(args.include)) if (basicAuth !== undefined) headers.set('authorization', `Basic ${btoa(`${basicAuth.username}:${basicAuth.password}`)}`) const url = `${baseUrl.replace(/\/+$/, '')}/api/metric-cards${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(metricCardList, await res.json()) };