import type { BooleanFlag, OptionFlag } from '@oclif/core/interfaces'; export declare const TICKET_CATEGORIES: readonly ["encoding", "player", "analytics", "other"]; export declare const TICKET_STATUSES: readonly ["new", "open", "pending", "hold", "solved", "closed", "deleted"]; export declare const TICKET_PRIORITIES: readonly ["blocker", "high", "medium", "low"]; export declare const TICKET_SEVERITIES: readonly ["high", "medium", "low", "minor"]; export declare const TICKET_SORT_FIELDS: readonly ["createdAt", "modifiedAt"]; export declare const MAX_LIMIT = 100; export declare const MAX_SEARCH_TEXT_LENGTH = 100; export declare const MAX_COMMENT_LENGTH = 65536; /** * The API's ticket `body` is only checked for non-emptiness, so this bound is the * CLI's own: the body goes into a ticket that cannot be withdrawn via the API, and * an unbounded `--body-file` would push the confirmation warning off screen. * Matches the comment limit for consistency. */ export declare const MAX_BODY_LENGTH = 65536; /** * Head-and-tail view of a long value, so a preview stays readable and honest about * size. `tailChars = 0` gives a head-only view. * * NOTE the explicit `tailChars > 0` guard: `slice(-0)` is `slice(0)`, i.e. the whole * string, so the obvious one-liner printed the entire text *and* labelled it as * truncated — worst of both, since the point is to keep a confirmation warning on * screen. */ export declare function abbreviate(text: string, headChars?: number, tailChars?: number): string; /** Stands in for an attachment URL that was withheld. See {@link redactAttachmentUrls}. */ export declare const HIDDEN_ATTACHMENT_URL = "[url hidden \u2014 pass --show-secrets]"; /** * Replaces attachment download URLs with {@link HIDDEN_ATTACHMENT_URL}. * * The URL is a capability: the API documents the file as downloadable by anyone * holding the link, so it is masked like any other secret unless `--show-secrets` is * passed, matching `account info`. Applied to the payload before output rather than * while rendering the human view — `--json` (which the `--jq` example steers users * towards) would otherwise put the download link straight into a CI log or a shared * terminal session. * * The key is kept with a placeholder rather than deleted, so a JSON consumer can * still see that the attachment has a URL to ask for. * * Scope, deliberately: this masks the structured `attachments[].url` and nothing * else. A link that appears *inside* comment text (an inline image in `htmlBody`, a * URL someone typed) is printed as authored — that text is what the command exists * to show, and pattern-matching URLs out of it would be unreliable in both * directions while suggesting a completeness this does not have. */ export declare function redactAttachmentUrls(detail: SupportTicketDetail): SupportTicketDetail; /** Newest comment on a ticket, by createdAt, for the comment preview. */ export declare function latestComment(ticket: SupportTicketDetail): SupportTicketComment | undefined; /** CLI-friendly flag values mapped to the API's Zendesk field values. */ export declare const REQUEST_TYPES: Record; export declare const REPRODUCIBLE_WITH_SAMPLE_APP: Record; export declare const REPRODUCIBLE_RELIABLY: Record; export interface SupportTicket extends Record { caseId?: number; externalId?: string; subject?: string; category?: string; status?: string; priority?: string; severity?: string; createdAt?: string; modifiedAt?: string; } export interface SupportTicketComment { id?: number; body?: string; htmlBody?: string; createdAt?: string; author?: { name?: string; agent?: boolean; }; attachments?: { id?: number; fileName?: string; contentType?: string; size?: number; url?: string; }[]; } export interface SupportTicketDetail extends SupportTicket { requester?: { name?: string; agent?: boolean; }; organization?: { id?: string; name?: string; }; comments?: SupportTicketComment[]; } export interface SupportTicketPage { items?: SupportTicket[]; totalCount?: number; previous?: string; next?: string; } export interface ListTicketsOptions { limit: number; offset: number; status?: string; category?: string; priority?: string; severity?: string; searchText?: string; sort?: string; } export interface RequestContext { tenantOrgId?: string; apiKey?: string; } export declare function listTickets(options: ListTicketsOptions, context: RequestContext): Promise; export declare function getTicket(caseId: string, context: RequestContext): Promise; export interface CreatedTicket { id?: number; subject?: string; } export declare function createTicket(payload: Record, context: RequestContext): Promise; export interface CommentPayload extends Record { htmlBody: string; /** The ticket's last known modifiedAt — the API requires it for collision protection. */ updatedStamp: string; } export interface AddedComment { caseId?: number; modifiedAt?: string; } export declare function addComment(caseId: string, payload: CommentPayload, context: RequestContext): Promise; /** * The API accepts any non-negative offset but silently serves an earlier page * unless the offset lands on a page boundary, so reject that client-side rather * than returning duplicate results. */ export declare function validatePagination(limit: number, offset: number): string | undefined; /** The API rejects punctuation in searchText, and truncating silently would change the query. */ export declare function validateSearchText(searchText: string): string | undefined; /** * Validates a comma-separated filter value (the API accepts several values per * filter) against the allowed set, case-insensitively. */ export declare function validateEnumFilter(flagName: string, value: string, allowed: readonly string[]): string | undefined; /** * Normalizes a sort expression to what the API matches on. * * `validateSort` accepts `createdAt:desc` case-insensitively, so it must be sent * uppercased — otherwise validation passes and the API silently ignores the * direction, the same class of bug `normalizeEnumFilter` exists to prevent. */ export declare function normalizeSort(sort: string): string; /** * Normalizes a comma-separated filter to what the API can parse. * * Validation above trims each part, but the API splits on `,` and uppercases * *without* trimming — so `--status "open, pending"` would pass validation here and * still come back as HTTP 400, exactly the round trip the local check exists to * avoid. Send what we validated. */ export declare function normalizeEnumFilter(value: string): string; export declare function validateSort(sort: string): string | undefined; /** * The optional create-ticket fields, declared once. * * The oclif flags, the accepted flag type, and the API payload key all come from * this table. Previously the same ~18 fields were listed three times — flag * definition, TypeScript interface, payload mapping — and the call site cast the * parsed flags, so a field added to two of the three compiled cleanly and then never * reached the API. Add a field here and it is wired end to end. */ export declare const CREATE_TICKET_FIELDS: readonly [{ readonly flag: "subject"; readonly payload: "subject"; readonly description: "Ticket subject"; }, { readonly flag: "priority"; readonly payload: "priority"; readonly description: "Ticket priority"; readonly options: readonly ["blocker", "high", "medium", "low"]; }, { readonly flag: "severity"; readonly payload: "severity"; readonly description: "Ticket severity"; readonly options: readonly ["high", "medium", "low", "minor"]; }, { readonly flag: "platform"; readonly payload: "platform"; readonly description: "Affected platform (e.g. web, android, ios, roku)"; }, { readonly flag: "sdk-version"; readonly payload: "sdkVersion"; readonly description: "SDK / player version in use"; }, { readonly flag: "encoding-id"; readonly payload: "encodingId"; readonly description: "Affected encoding ID (requires --category encoding)"; }, { readonly flag: "license"; readonly payload: "license"; readonly description: "Affected license key (requires --category player or analytics)"; }, { readonly flag: "page-url"; readonly payload: "pageUrl"; readonly description: "URL where the issue reproduces (requires --category player or analytics)"; }, { readonly flag: "allow-file-access"; readonly payload: "allowFileAccess"; readonly description: "Allow Bitmovin support to access the referenced files (requires --category encoding)"; readonly type: "boolean"; }, { readonly flag: "input-url"; readonly payload: "inputUrl"; readonly description: "Input / stream URL involved"; }, { readonly flag: "request-type"; readonly payload: "requestType"; readonly description: "Kind of request"; readonly values: Record; }, { readonly flag: "reference-id"; readonly payload: "referenceId"; readonly description: "Your own reference (e.g. internal ticket id)"; }, { readonly flag: "reproducible-with-sample-app"; readonly payload: "reproducibleWithSampleApp"; readonly description: "Whether the issue reproduces in the Bitmovin sample app"; readonly values: Record; }, { readonly flag: "reproducible-reliably"; readonly payload: "reproducibleReliably"; readonly description: "Whether the issue reproduces reliably"; readonly values: Record; }, { readonly flag: "os-details"; readonly payload: "osDetails"; readonly description: "Operating system details"; }, { readonly flag: "device-details"; readonly payload: "deviceDetails"; readonly description: "Device details"; }, { readonly flag: "geo-restriction-country"; readonly payload: "geoRestrictionCountry"; readonly description: "Country the issue is restricted to"; }]; export interface CreateTicketFlags extends Record { body: string; category: string; } /** * Builds the create-ticket request body. * * `organizationId` is always set from the resolved tenant organization (never * from a separate flag): the API rejects the request when the body's * `organizationId` disagrees with the `X-Tenant-Org-Id` header, so the two can * only ever be set together. */ export declare function buildCreateTicketPayload(flags: CreateTicketFlags, tenantOrgId?: string): Record; /** Flag name of every field in {@link CREATE_TICKET_FIELDS}. */ export type CreateTicketFlagName = (typeof CREATE_TICKET_FIELDS)[number]['flag']; type CreateTicketField = Extract<(typeof CREATE_TICKET_FIELDS)[number], { flag: Name; }>; /** Boolean fields parse to `boolean`, everything else to `string | undefined`. */ type CreateTicketFlag = CreateTicketField extends { type: 'boolean'; } ? BooleanFlag : OptionFlag; /** Exact per-flag types, so `flags['sdk-version']` is a `string` and not a union with `boolean`. */ export type CreateTicketFlagDefinitions = { [Name in CreateTicketFlagName]: CreateTicketFlag; }; /** * oclif flag definitions derived from {@link CREATE_TICKET_FIELDS}, so the flags and * the payload mapping cannot diverge. Spread into a command's `flags`. * * The return type names every flag explicitly. `Object.fromEntries` alone widens to * `{[k: string]: Flag}`, which erases the keys from oclif's parsed-flags type — then * `flags['sdk-version']` stops compiling and the only thing keeping the command * building is a cast, leaving no compile-time check anywhere on the flag→payload * chain. */ export declare function createTicketFlags(): CreateTicketFlagDefinitions; /** * Category-gated fields. * * The API does NOT reject these when the category does not match — it maps them * only inside the branch for their category and otherwise drops them silently, so * the create succeeds while the data disappears. That is why the check lives here: * without it, `--category player --allow-file-access` would leave the user * believing they granted support access to their files while support sees no such * field. Do not relax this expecting a loud API error. */ export declare function validateCreateTicketPayload(payload: Record): string | undefined; /** * Comments are posted as `htmlBody`. Plain text is escaped and its line breaks * converted, so a multi-line terminal/file input does not collapse into one * paragraph and `<`/`&` in log excerpts survive verbatim. `--html` passes the * input through untouched (the API sanitizes it server-side either way). */ export declare function toHtmlBody(text: string, isHtml: boolean): string; /** * Resolves the text a write command sends, from `--body` or `--body-file`. * * Shared by `tickets create` and `tickets comment`: both accept the same flag pair * and both need the same bound, and while this lived in each command the two had * already drifted — only `create` applied the length cap, so a huge `--body-file` * reached the comment confirmation and scrolled the warning off screen. * * Bounded because the text goes into a ticket that cannot be withdrawn via the API, * and because an enormous body degrades the confirmation exactly when it matters * most. Returns the problem as a message instead of throwing, so the caller keeps * control of the oclif exit code. */ export declare function resolveBodyInput(options: { body?: string; bodyFile?: string; /** Named in the "is required" message, e.g. `ticket body`. */ what: string; maxLength: number; }): { text: string; } | { problem: string; }; export declare function validateCommentBody(htmlBody: string): string | undefined; export {}; //# sourceMappingURL=support-tickets.d.ts.map