import {z} from 'zod' export type GetApiV1ForecastsModelsModelIdArgs = {model_id: string}; export type GetApiV1ForecastsModelsModelIdOptions = {baseUrl?: string | undefined, BearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const algoType = z.literal("phq-xgboost"); export const publicInterval = z.literal("day"); export const industry = z.enum(["accommodation", "cpg", "tourism", "marketing", "parking", "restaurants", "retail", "transportation", "other"]); export const publicDemandType = z.object({interval: publicInterval.nullable().optional(), industry: industry.nullable().optional()}); export const forecastWindowDay = z.enum(["1d", "7d", "14d", "28d", "30d", "60d", "90d"]); export const geoPoint = z.object({lat: z.string(), lon: z.string()}); export const location = z.object({geopoint: geoPoint.optional(), radius: z.number().gt(0).optional(), unit: z.enum(["m", "mi", "km", "ft"]).optional(), saved_location_id: z.string().min(1).max(256).optional()}); export const accuracy = z.object({mape: z.number(), mae: z.number(), rmse: z.number(), wape: z.number()}); export const dateRange = z.object({start: z.string(), end: z.string()}); export const demandDataMetrics = z.object({date_range: dateRange}); export const trainingDataMetrics = z.object({date_range: dateRange, missing_pct: z.number().gte(0).lte(100).optional(), missing_dates: z.array(z.string()).nullable().optional()}); export const publicMetrics = z.object({accuracy: accuracy.nullable().optional(), demand_data: demandDataMetrics, training_data: trainingDataMetrics.nullable().optional()}); export const readinessStatus = z.enum(["created", "failed", "forecasting", "preparing", "ready", "stale", "training"]); export const readiness = z.object({status: readinessStatus, error_code: z.string().nullable().optional(), error_message: z.string().nullable().optional()}); export const publicForecastModel = z.object({algo: algoType, create_dt: z.string(), demand_type: publicDemandType.nullable().optional(), external_id: z.string().min(1).nullable().optional(), forecast_window: forecastWindowDay, label: z.array(z.string().min(1)).nullable().optional(), location: location, metrics: publicMetrics.nullable().optional(), model_id: z.string().min(1), name: z.string().min(1), readiness: readiness, train_dt: z.string().nullable().optional(), update_dt: z.string()}); export const getModelResponse = z.object({errors: z.array(z.string()).optional(), warnings: z.array(z.string()).optional(), model: publicForecastModel}); 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 Model * * GET /v1/forecasts/models/{model_id} */ export const getApiV1ForecastsModelsModelId = async (args: GetApiV1ForecastsModelsModelIdArgs, options?: GetApiV1ForecastsModelsModelIdOptions) => { const {baseUrl = "https://api.predicthq.com", fetch: fetchFn = fetch, BearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (BearerAuth !== undefined) headers.set('authorization', `Bearer ${BearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/v1/forecasts/models/${encodeURIComponent(String(args.model_id))}${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(getModelResponse, await res.json()) };