import {z} from 'zod' export type ProductAnalyticsRetentionIndexTargetType = 'index'; export type ProductAnalyticsRetentionIndexTarget = {type: ProductAnalyticsRetentionIndexTargetType, value: number}; export type ProductAnalyticsRetentionAggregationTargetType = 'aggregation'; export type ProductAnalyticsRetentionAggregationTarget = {type: ProductAnalyticsRetentionAggregationTargetType, value: string}; export type ProductAnalyticsRetentionCohortTarget = ProductAnalyticsRetentionIndexTarget | ProductAnalyticsRetentionAggregationTarget; export type ProductAnalyticsRetentionCohortScopeType = 'cohort'; export type ProductAnalyticsRetentionCohortScope = {target: ProductAnalyticsRetentionCohortTarget, type: ProductAnalyticsRetentionCohortScopeType}; export type ProductAnalyticsRetentionReturnPeriodScopeType = 'return_period'; export type ProductAnalyticsRetentionReturnPeriodScope = {target: ProductAnalyticsRetentionIndexTarget, type: ProductAnalyticsRetentionReturnPeriodScopeType}; export type ProductAnalyticsRetentionCellScopeType = 'cell'; export type ProductAnalyticsRetentionCellScope = {cohort_target: ProductAnalyticsRetentionCohortTarget, return_period_target: ProductAnalyticsRetentionIndexTarget, type: ProductAnalyticsRetentionCellScopeType}; export type ProductAnalyticsRetentionScope = ProductAnalyticsRetentionCohortScope | ProductAnalyticsRetentionReturnPeriodScope | ProductAnalyticsRetentionCellScope; export type ProductAnalyticsRetentionComputeMetric = '__dd.retention' | '__dd.retention_rate'; export type ProductAnalyticsRetentionCompute = {aggregation: string, metric: ProductAnalyticsRetentionComputeMetric}; export type QuerySortOrder = 'asc' | 'desc'; export type ProductAnalyticsGroupBySort = {aggregation?: string | undefined, metric?: string | undefined, order?: QuerySortOrder | undefined}; export type ProductAnalyticsRetentionGroupByTarget = 'cohort' | 'return_period'; export type ProductAnalyticsRetentionGroupBy = {facet: string, limit?: number | undefined, should_exclude_missing?: boolean | undefined, sort?: ProductAnalyticsGroupBySort | undefined, source?: string | undefined, target: ProductAnalyticsRetentionGroupByTarget}; export type ProductAnalyticsEventQueryDataSource = 'product_analytics'; export type ProductAnalyticsEventSearch = {query?: string | undefined}; export type ProductAnalyticsEventQuery = {data_source: ProductAnalyticsEventQueryDataSource, search: ProductAnalyticsEventSearch}; export type ProductAnalyticsOccurrenceQueryDataSource = 'product_analytics_occurrence'; export type ProductAnalyticsOccurrenceFilter = {meta?: {[key: string]: string} | undefined, operator: string, value: string}; export type ProductAnalyticsOccurrenceSearch = {occurrences?: ProductAnalyticsOccurrenceFilter | undefined, query?: string | undefined}; export type ProductAnalyticsOccurrenceQuery = {data_source: ProductAnalyticsOccurrenceQueryDataSource, search: ProductAnalyticsOccurrenceSearch}; export type ProductAnalyticsBaseQuery = ProductAnalyticsEventQuery | ProductAnalyticsOccurrenceQuery; export type ProductAnalyticsRetentionCalendarTimeIntervalType = 'calendar'; export type ProductAnalyticsCalendarIntervalType = 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'; export type ProductAnalyticsCalendarInterval = {alignment?: string | undefined, quantity?: number | undefined, timezone?: string | undefined, type: ProductAnalyticsCalendarIntervalType}; export type ProductAnalyticsRetentionCalendarTimeInterval = {type: ProductAnalyticsRetentionCalendarTimeIntervalType, value: ProductAnalyticsCalendarInterval}; export type ProductAnalyticsRetentionFixedTimeIntervalType = 'fixed'; export type ProductAnalyticsRetentionFixedTimeIntervalUnit = 'day' | 'week' | 'month'; export type ProductAnalyticsRetentionFixedTimeInterval = {type: ProductAnalyticsRetentionFixedTimeIntervalType, unit: ProductAnalyticsRetentionFixedTimeIntervalUnit, value: number}; export type ProductAnalyticsRetentionTimeInterval = ProductAnalyticsRetentionCalendarTimeInterval | ProductAnalyticsRetentionFixedTimeInterval; export type ProductAnalyticsRetentionCohortCriteria = {base_query: ProductAnalyticsBaseQuery, time_interval: ProductAnalyticsRetentionTimeInterval}; export type ProductAnalyticsAudienceAccountSubquery = {name: string, query?: string | undefined}; export type ProductAnalyticsAudienceSegmentSubquery = {name: string, segment_id: string}; export type ProductAnalyticsAudienceUserSubquery = {name: string, query?: string | undefined}; export type ProductAnalyticsAudienceFilters = {accounts?: Array | undefined, formula?: string | undefined, segments?: Array | undefined, users?: Array | undefined}; export type ProductAnalyticsRetentionFilters = {audience_filters?: ProductAnalyticsAudienceFilters | undefined, string_filter?: string | undefined}; export type ProductAnalyticsRetentionEntity = '@usr.id' | '@account.id'; export type ProductAnalyticsRetentionReturnCondition = 'conversion_on' | 'conversion_on_or_after'; export type ProductAnalyticsRetentionReturnCriteria = {base_query: ProductAnalyticsBaseQuery, time_interval?: ProductAnalyticsRetentionTimeInterval | undefined}; export type ProductAnalyticsRetentionSearch = {cohort_criteria: ProductAnalyticsRetentionCohortCriteria, filters?: ProductAnalyticsRetentionFilters | undefined, retention_entity: ProductAnalyticsRetentionEntity, return_condition: ProductAnalyticsRetentionReturnCondition, return_criteria?: ProductAnalyticsRetentionReturnCriteria | undefined}; export type ProductAnalyticsRetentionGridQuery = {computation_scope?: ProductAnalyticsRetentionScope | undefined, compute: ProductAnalyticsRetentionCompute, group_by?: Array | undefined, search: ProductAnalyticsRetentionSearch}; export type ProductAnalyticsRetentionGridRequestAttributes = {exclude_anonymous_traffic?: boolean | undefined, from: number, query: ProductAnalyticsRetentionGridQuery, to: number}; export type ProductAnalyticsRetentionGridRequestType = 'retention_grid_request'; export type ProductAnalyticsRetentionGridRequestData = {attributes: ProductAnalyticsRetentionGridRequestAttributes, type: ProductAnalyticsRetentionGridRequestType}; export type ProductAnalyticsRetentionGridRequest = {data: ProductAnalyticsRetentionGridRequestData}; export type CreateApiApiV2ProductAnalyticsRetentionGridArgs = {body: ProductAnalyticsRetentionGridRequest}; export type CreateApiApiV2ProductAnalyticsRetentionGridOptions = {baseUrl?: string | undefined, apiKeyAuth?: string | undefined, appKeyAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const productAnalyticsRetentionGridCohortType = z.enum(["raw", "aggregated"]); export const productAnalyticsRetentionGridCohortCell = z.object({cell_count: z.number().int().optional(), cell_rate: z.number().optional(), cell_relative_value_change: z.number().nullable().optional(), cell_value: z.number().nullable().optional(), is_partial_data: z.boolean().optional(), return_period_end_time: z.number().int().optional(), return_period_index: z.number().int().optional(), return_period_start_time: z.number().int().optional(), type: productAnalyticsRetentionGridCohortType.optional()}); export const productAnalyticsUnit = z.object({family: z.string().optional(), id: z.number().int().optional(), name: z.string().optional(), plural: z.string().optional(), scale_factor: z.number().optional(), short_name: z.string().optional()}); export const productAnalyticsRetentionGridCohort = z.object({cells: z.array(productAnalyticsRetentionGridCohortCell).optional(), cohort_end_time: z.number().int().optional(), cohort_index: z.number().int().optional(), cohort_size: z.number().int().optional(), cohort_start_time: z.number().int().optional(), group_tags: z.array(z.string()).optional(), name: z.string().optional(), type: productAnalyticsRetentionGridCohortType.optional(), unit: z.array(productAnalyticsUnit).optional()}); export const productAnalyticsRetentionPeriod = z.object({unit: z.string().optional(), value: z.number().int().optional()}); export const productAnalyticsRetentionGridResponseAttributes = z.object({cohorts: z.array(productAnalyticsRetentionGridCohort).optional(), retention_entity: z.string().optional(), retention_periods: z.array(productAnalyticsRetentionPeriod).optional(), unit: z.array(productAnalyticsUnit).optional()}); export const productAnalyticsRetentionGridResponseType = z.literal("retention_grid_response"); export const productAnalyticsRetentionGridResponseData = z.object({attributes: productAnalyticsRetentionGridResponseAttributes, id: z.string(), type: productAnalyticsRetentionGridResponseType}); export const productAnalyticsRetentionGridResponse = z.object({data: productAnalyticsRetentionGridResponseData}); 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 }; /** * Compute a retention grid * * POST /api/v2/product-analytics/retention/grid * * Also accepts auth: AuthZ */ export const createApiApiV2ProductAnalyticsRetentionGrid = async (args: CreateApiApiV2ProductAnalyticsRetentionGridArgs, options?: CreateApiApiV2ProductAnalyticsRetentionGridOptions) => { const {baseUrl = "https://api.datadoghq.com", fetch: fetchFn = fetch, apiKeyAuth, appKeyAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (apiKeyAuth !== undefined) headers.set("DD-API-KEY", apiKeyAuth) if (appKeyAuth !== undefined) headers.set("DD-APPLICATION-KEY", appKeyAuth) const url = `${baseUrl.replace(/\/+$/, '')}/api/v2/product-analytics/retention/grid${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(productAnalyticsRetentionGridResponse, await res.json()) };