import { z } from 'zod'; import { healthcheck } from '../../operators/healthCheck.js'; import { request } from '../../operators/request.js'; import { Configuration, Metadata, Pagination } from '../../shared.js'; import type { ThreekitAuthProps } from '../../ThreekitAuthProps.js'; import { Route } from '../Route.js'; export const EventType = z.enum([ 'product download', 'product session start', 'product session end', 'product configuration start', 'product configuration attribute set', 'product cart-add', 'product ordered', 'product social share', 'product AR not available', 'product AR offered', 'product AR download', 'product AR mobile transition offered', 'product AR mobile transition completed' ]); export type EventType = z.infer; const EventBase = z.object({ eventType: EventType, eventMetadata: Metadata, assetId: z.string().uuid().optional(), userId: z.string().uuid().optional(), sessionId: z.string().uuid().optional(), configId: z.string().uuid().nullable().optional(), configuration: Configuration.optional(), device: z.string().optional(), metric: z.number().optional() }); export const Event = z .object({ id: z.string().uuid(), createdAt: z.string().optional(), requestUrl: z.string().nullable(), requestOrigin: z.string().nullable(), referer: z.string() }) .merge(EventBase); export type Event = z.infer; export const EventListing = Pagination.merge( z.object({ events: z.array(Event) }) ); export type EventListing = z.infer; export const CreateEventProps = EventBase; export type CreateEventProps = z.infer; export const QueryEventProps = z.object({ orgId: z.string().uuid().optional(), metadata: Metadata.optional(), device: z.string().optional(), referer: z.string().optional() }); export type QueryEventProps = z.infer; export enum QueryRange { Day = 'day', Month = 'month', Year = 'year' } export const QueryViewsProps = z.object({ orgId: z.string().uuid().optional(), metadata: Metadata.optional(), device: z.string().optional(), referer: z.string().optional(), subStartDate: z.string().optional(), endDate: z.string().optional(), range: z.nativeEnum(QueryRange).optional(), eventType: EventType.optional() }); export type QueryViewsProps = z.infer; export const Views = z.object({ year: z.number(), month: z.number().optional(), // only exists if queries using range: month day: z.number().optional(), // only exists if queries using range: day views: z.number(), cumulative: z.number() }); export const ViewsListing = Pagination.merge( z.object({ views: z.array(Views) }) ); export type ViewsListing = z.infer; const API_ROUTE = `/api/analytics`; export class Analytics extends Route { constructor(auth: ThreekitAuthProps) { super(auth, API_ROUTE); } healthcheck() { return healthcheck(this.context); } create(createProps: CreateEventProps) { return request(this.context, { method: 'POST', url: 'events', data: createProps }); } getById(id: string) { const appId = z.string().uuid().parse(id); return request(this.context, { url: `events/${appId}` }); } // NOTE: this is purposely disabled, see this conversation: https://threekit.slack.com/archives/CDHMWSL80/p1710957446559079 get(queryProps?: QueryEventProps) { return request(this.context, { url: 'events', params: queryProps }); } getViews(queryProps?: QueryViewsProps) { return request(this.context, { url: 'events/views', params: queryProps }); } }