import {z} from 'zod' export type GetApiEnvironmentsEnvIdAnalyticsDashboardsDashboardIdOptions = {baseUrl: string, fetch?: typeof fetch | undefined}; export const widgetType = z.enum(["stats", "doughnut", "pie", "polarArea", "time-series-line", "time-series-bar", "vertical-bar", "horizontal-bar"]); export const widgetLayout = z.object({cols: z.number().int().gte(1), rows: z.number().int().gte(1), x: z.number().int().gte(0), y: z.number().int().gte(0)}); export const timeRange = z.object({from: z.string(), to: z.string()}); export const metricName = z.enum(["HTTP_REQUESTS", "HTTP_ERRORS", "HTTP_ERROR_RATE", "HTTP_REQUEST_CONTENT_LENGTH", "HTTP_RESPONSE_CONTENT_LENGTH", "HTTP_ENDPOINT_RESPONSE_TIME", "HTTP_GATEWAY_RESPONSE_TIME", "HTTP_GATEWAY_LATENCY", "LLM_PROMPT_TOKEN_SENT", "LLM_PROMPT_TOKEN_RECEIVED", "LLM_PROMPT_TOKEN_SENT_COST", "LLM_PROMPT_TOKEN_RECEIVED_COST", "LLM_PROMPT_TOTAL_TOKEN", "LLM_PROMPT_TOKEN_TOTAL_COST", "MESSAGE_PAYLOAD_SIZE", "MESSAGES", "MESSAGE_ERRORS", "MESSAGE_GATEWAY_LATENCY", "EDGE_DETECTION_COUNT", "EDGE_TOKENS_IN", "EDGE_TOKENS_OUT", "EDGE_HEARTBEAT_COUNT", "NATIVE_CONNECTIONS_SUMMARY", "NATIVE_MESSAGES_PRODUCED_DOWNSTREAM", "NATIVE_MESSAGES_PRODUCED_UPSTREAM", "NATIVE_MESSAGES_CONSUMED_DOWNSTREAM", "NATIVE_MESSAGES_CONSUMED_UPSTREAM", "NATIVE_BYTES_PRODUCED_DOWNSTREAM", "NATIVE_BYTES_PRODUCED_UPSTREAM", "NATIVE_BYTES_CONSUMED_DOWNSTREAM", "NATIVE_BYTES_CONSUMED_UPSTREAM", "NATIVE_ACTIVE_CONNECTIONS_DOWNSTREAM", "NATIVE_ACTIVE_CONNECTIONS_UPSTREAM", "NATIVE_AUTHENTICATIONS_SUCCESS_DOWNSTREAM", "NATIVE_AUTHENTICATIONS_SUCCESS_UPSTREAM", "NATIVE_AUTHENTICATIONS_FAILURE_DOWNSTREAM", "NATIVE_AUTHENTICATIONS_FAILURE_UPSTREAM", "NATIVE_OPERATIONS_RECEIVED", "NATIVE_OPERATIONS_FORWARDED", "NATIVE_OPERATIONS_ANSWERED", "NATIVE_OPERATIONS_COMPLETED", "NATIVE_OPERATION_GATEWAY_REQUEST_DURATION", "NATIVE_OPERATION_BROKER_DURATION", "NATIVE_OPERATION_GATEWAY_RESPONSE_DURATION"]); export const measureName = z.enum(["AVG", "MIN", "MAX", "P50", "P90", "P95", "P99", "COUNT", "PERCENTAGE", "SUM"]); export const filterName = z.enum(["API", "APPLICATION", "PLAN", "API_PRODUCT", "GATEWAY", "TENANT", "ZONE", "HTTP_METHOD", "HTTP_STATUS_CODE_GROUP", "HTTP_STATUS", "HTTP_PATH", "HTTP_PATH_MAPPING", "HOST", "GEO_IP_COUNTRY", "GEO_IP_REGION", "GEO_IP_CITY", "GEO_IP_CONTINENT", "CONSUMER_IP", "HTTP_USER_AGENT_OS_NAME", "HTTP_USER_AGENT_DEVICE", "MESSAGE_CONNECTOR_TYPE", "MESSAGE_CONNECTOR_ID", "MESSAGE_OPERATION_TYPE", "MESSAGE_SIZE", "MESSAGE_COUNT", "MESSAGE_ERROR_COUNT", "HTTP_ENDPOINT_RESPONSE_TIME", "HTTP_GATEWAY_LATENCY", "HTTP_GATEWAY_RESPONSE_TIME", "HTTP_REQUEST_CONTENT_LENGTH", "HTTP_RESPONSE_CONTENT_LENGTH", "LLM_PROXY_MODEL", "LLM_PROXY_PROVIDER", "MCP_PROXY_METHOD", "MCP_PROXY_TOOL", "MCP_PROXY_RESOURCE", "MCP_PROXY_PROMPT", "API_TYPE", "ERROR_KEY", "REQUEST_ID", "TRANSACTION_ID", "EDGE_PROVIDER", "EDGE_PROCESS", "EDGE_CLIENT", "EDGE_TYPE", "EDGE_VERSION", "EDGE_MODEL", "EDGE_TOOL", "NATIVE_CONNECTION_STATUS", "NATIVE_FAILURE_SIDE", "NATIVE_CLIENT_ID", "NATIVE_TOPIC", "NATIVE_OPERATION", "URI", "ENTRYPOINT"]); export const operator = z.enum(["EQ", "IN", "LTE", "GTE", "CONTAINS"]); export const stringFilter = z.object({name: filterName, operator: operator, value: z.string()}); export const numberFilter = z.object({name: filterName, operator: operator, value: z.number().int()}); export const arrayFilter = z.object({name: filterName, operator: operator, value: z.array(z.string())}); export const filter = z.discriminatedUnion("operator", [stringFilter, numberFilter, arrayFilter]); export const metricRequest = z.object({name: metricName, measures: z.array(measureName).optional(), filters: z.array(filter).optional()}); export const interval = z.union([z.string(), z.number()]); export const facetName = z.enum(["API", "APPLICATION", "PLAN", "API_PRODUCT", "GATEWAY", "TENANT", "ZONE", "HTTP_METHOD", "HTTP_STATUS_CODE_GROUP", "HTTP_STATUS", "HTTP_PATH", "HTTP_PATH_MAPPING", "HOST", "GEO_IP_COUNTRY", "GEO_IP_REGION", "GEO_IP_CITY", "GEO_IP_CONTINENT", "CONSUMER_IP", "HTTP_USER_AGENT_OS_NAME", "HTTP_USER_AGENT_DEVICE", "MESSAGE_CONNECTOR_TYPE", "MESSAGE_CONNECTOR_ID", "MESSAGE_OPERATION_TYPE", "LLM_PROXY_MODEL", "LLM_PROXY_PROVIDER", "MCP_PROXY_METHOD", "MCP_PROXY_TOOL", "MCP_PROXY_RESOURCE", "MCP_PROXY_PROMPT", "EDGE_PROVIDER", "EDGE_PROCESS", "EDGE_CLIENT", "EDGE_TYPE", "EDGE_VERSION", "EDGE_MODEL", "EDGE_TOOL", "NATIVE_CONNECTION_STATUS", "NATIVE_FAILURE_SIDE", "NATIVE_CLIENT_ID", "NATIVE_TOPIC", "NATIVE_OPERATION"]); export const widgetRequest = z.object({type: z.enum(["measures", "facets", "time-series"]), timeRange: timeRange, metrics: z.array(metricRequest), interval: interval.optional(), by: z.array(facetName).optional(), limit: z.number().int().gte(1).optional(), filters: z.array(filter).optional()}); export const widget = z.object({id: z.string(), title: z.string().min(3).max(256), description: z.string().max(512).optional(), type: widgetType, layout: widgetLayout, request: widgetRequest}); export const dashboard = z.object({id: z.string(), name: z.string(), createdBy: z.string(), createdAt: z.string(), lastModified: z.string(), labels: z.record(z.string(), z.string()).optional(), widgets: z.array(widget)}); 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 }; /** * Get a custom analytics dashboard * * GET /environments/{envId}/analytics/dashboards/{dashboardId} */ export const getApiEnvironmentsEnvIdAnalyticsDashboardsDashboardId = async (options: GetApiEnvironmentsEnvIdAnalyticsDashboardsDashboardIdOptions) => { const {baseUrl, fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") const url = `${baseUrl.replace(/\/+$/, '')}/environments/${encodeURIComponent(String(args.envId))}/analytics/dashboards/${encodeURIComponent(String(args.dashboardId))}${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(dashboard, await res.json()) };