import {z} from 'zod' export type DeviceId = string; export type PageSort = 'asc' | 'desc'; export type ISODateTimeString = string; export type PageLimit = number; export type PageNextToken = string; export type DeviceTag = string; export type GetApiLocationHistoryArgs = {deviceId?: DeviceId | undefined, latest?: boolean | undefined, pageSort?: PageSort | undefined, start?: ISODateTimeString | undefined, end?: ISODateTimeString | undefined, pageLimit?: PageLimit | undefined, pageNextToken?: PageNextToken | undefined, deviceIdentifier?: DeviceId | undefined, inclusiveStart?: ISODateTimeString | undefined, inclusiveEnd?: ISODateTimeString | undefined, tags?: Array | undefined}; export type GetApiLocationHistoryOptions = {baseUrl?: string | undefined, SimpleToken?: string | undefined, fetch?: typeof fetch | undefined}; export const locationTrackerId = z.string(); export const deviceId = z.string(); export const trackerServiceType = z.enum(["GNSS", "GPS", "MCELL", "MCELL_EVAL", "SCELL", "SCELL_EVAL", "WIFI", "WIFI_EVAL"]); export const iSODateTimeString = z.string(); export const trackerLatitude = z.string(); export const trackerLongitude = z.string(); export const accuracy = z.number(); export const altitude = z.number(); export const speed = z.number(); export const heading = z.number(); export const gnssMeta = z.object({acc: accuracy, alt: altitude, spd: speed, hdg: heading}); export const trackerUncertainty = z.string(); export const locationTrackerItem = z.object({id: locationTrackerId, deviceId: deviceId, serviceType: trackerServiceType, insertedAt: iSODateTimeString, recordedAt: iSODateTimeString.optional(), lat: trackerLatitude, lon: trackerLongitude, meta: gnssMeta, uncertainty: trackerUncertainty}); export const paginatedResultLocationTrackerItem = z.object({items: z.array(locationTrackerItem), total: z.number().int().gte(0).optional(), pageNextToken: z.string().optional()}); 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 }; /** * GetLocationHistory * * GET /location/history * * Also accepts auth: Organization Auth Token */ export const getApiLocationHistory = async (args: GetApiLocationHistoryArgs, options?: GetApiLocationHistoryOptions) => { const {baseUrl = "https://api.nrfcloud.com/v1", fetch: fetchFn = fetch, SimpleToken} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.deviceId != null) query.append("deviceId", String(args.deviceId)) if (args.latest != null) query.append("latest", String(args.latest)) if (args.pageSort != null) query.append("pageSort", String(args.pageSort)) if (args.start != null) query.append("start", String(args.start)) if (args.end != null) query.append("end", String(args.end)) if (args.pageLimit != null) query.append("pageLimit", String(args.pageLimit)) if (args.pageNextToken != null) query.append("pageNextToken", String(args.pageNextToken)) if (args.deviceIdentifier != null) query.append("deviceIdentifier", String(args.deviceIdentifier)) if (args.inclusiveStart != null) query.append("inclusiveStart", String(args.inclusiveStart)) if (args.inclusiveEnd != null) query.append("inclusiveEnd", String(args.inclusiveEnd)) for (const item of args.tags ?? []) query.append("tags", String(item)) if (SimpleToken !== undefined) headers.set('authorization', `Bearer ${SimpleToken}`) const url = `${baseUrl.replace(/\/+$/, '')}/location/history${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(paginatedResultLocationTrackerItem, await res.json()) };