feat: build vehicle data platform and production pipeline
This commit is contained in:
@@ -1,10 +1,33 @@
|
||||
import type {
|
||||
ApiEnvelope,
|
||||
AccessQuery,
|
||||
AccessSummary,
|
||||
AccessThresholdConfig,
|
||||
AccessThresholdUpdate,
|
||||
AccessUnresolvedIdentity,
|
||||
AccessUnresolvedIdentityQuery,
|
||||
AccessVehicleRow,
|
||||
AlertAction,
|
||||
AlertEvent,
|
||||
AlertNotification,
|
||||
AlertQuery,
|
||||
AlertRule,
|
||||
AlertRuleInput,
|
||||
AlertSummary,
|
||||
DailyMileageRow,
|
||||
DashboardSummary,
|
||||
HistoryLocationRow,
|
||||
HistoryDataResponse,
|
||||
HistorySeriesResponse,
|
||||
HistoryExportJob,
|
||||
HistoryExportRequest,
|
||||
HistoryMetricCatalog,
|
||||
MetricCatalog,
|
||||
LatestTelemetryResponse,
|
||||
MileageSummary,
|
||||
MapReverseGeocode,
|
||||
MonitorMapResponse,
|
||||
MonitorSummary,
|
||||
OnlineStatisticsSummary,
|
||||
OnlineVehicleStatusRow,
|
||||
OpsHealth,
|
||||
@@ -15,15 +38,22 @@ import type {
|
||||
RawFrameRow,
|
||||
RealtimeLocationRow,
|
||||
SourceReadinessPlan,
|
||||
SessionInfo,
|
||||
TrackPlaybackResponse,
|
||||
VehicleRealtimeRow,
|
||||
VehicleCoverageRow,
|
||||
VehicleCoverageSummary,
|
||||
VehicleDetail,
|
||||
VehicleProfile,
|
||||
VehicleProfileInput,
|
||||
VehicleProfileSyncRequest,
|
||||
VehicleProfileSyncResult,
|
||||
VehicleIdentityResolution,
|
||||
VehicleServiceOverview,
|
||||
VehicleServiceSummary,
|
||||
VehicleRow
|
||||
} from './types';
|
||||
import { getAccessToken } from '../v2/auth/session';
|
||||
|
||||
export type RawFrameQuery = {
|
||||
keyword?: string;
|
||||
@@ -54,7 +84,9 @@ type ApiErrorEnvelope = {
|
||||
};
|
||||
|
||||
async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const response = await fetch(path, init);
|
||||
const token = getAccessToken();
|
||||
const requestInit = token ? { ...init, headers: withAuthorization(init?.headers, token) } : init;
|
||||
const response = await fetch(path, requestInit);
|
||||
if (!response.ok) {
|
||||
throw new Error(await responseErrorMessage(response));
|
||||
}
|
||||
@@ -62,6 +94,12 @@ async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
return envelope.data;
|
||||
}
|
||||
|
||||
function withAuthorization(headers: HeadersInit | undefined, token: string) {
|
||||
const authorized = new Headers(headers);
|
||||
authorized.set('Authorization', `Bearer ${token}`);
|
||||
return authorized;
|
||||
}
|
||||
|
||||
async function responseErrorMessage(response: Response) {
|
||||
try {
|
||||
const envelope = (await response.json()) as ApiErrorEnvelope;
|
||||
@@ -85,12 +123,66 @@ function withTraceID(message: string, traceID?: string) {
|
||||
}
|
||||
|
||||
export const api = {
|
||||
session: () => request<SessionInfo>('/api/v2/session'),
|
||||
monitorSummary: (params = new URLSearchParams()) => request<MonitorSummary>(`/api/v2/monitor/summary?${params.toString()}`),
|
||||
monitorMap: (params = new URLSearchParams()) => request<MonitorMapResponse>(`/api/v2/monitor/map?${params.toString()}`),
|
||||
trackPlayback: (params = new URLSearchParams()) => request<TrackPlaybackResponse>(`/api/v2/tracks?${params.toString()}`),
|
||||
metricCatalog: () => request<MetricCatalog>('/api/v2/metrics'),
|
||||
historyMetricCatalog: () => request<HistoryMetricCatalog>('/api/v2/history/metrics'),
|
||||
historyData: (params = new URLSearchParams()) => request<HistoryDataResponse>(`/api/v2/history/query?${params.toString()}`),
|
||||
historySeries: (params = new URLSearchParams()) => request<HistorySeriesResponse>(`/api/v2/history/series?${params.toString()}`),
|
||||
historyExports: () => request<HistoryExportJob[]>('/api/v2/exports'),
|
||||
createHistoryExport: (query: HistoryExportRequest) => request<HistoryExportJob>('/api/v2/exports', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(query)
|
||||
}),
|
||||
accessSummary: (query: AccessQuery) => request<AccessSummary>('/api/v2/access/summary', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(query)
|
||||
}),
|
||||
accessVehicles: (query: AccessQuery) => request<Page<AccessVehicleRow>>('/api/v2/access/vehicles', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(query)
|
||||
}),
|
||||
accessUnresolvedIdentities: (query: AccessUnresolvedIdentityQuery) => request<Page<AccessUnresolvedIdentity>>('/api/v2/access/unresolved-identities', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(query)
|
||||
}),
|
||||
accessThresholds: () => request<AccessThresholdConfig>('/api/v2/access/thresholds'),
|
||||
updateAccessThresholds: (update: AccessThresholdUpdate) => request<AccessThresholdConfig>('/api/v2/access/thresholds', {
|
||||
method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(update)
|
||||
}),
|
||||
alertSummaryV2: (query: AlertQuery) => request<AlertSummary>('/api/v2/alerts/summary', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(query)
|
||||
}),
|
||||
alertEventsV2: (query: AlertQuery) => request<Page<AlertEvent>>('/api/v2/alerts/events', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(query)
|
||||
}),
|
||||
alertEventV2: (id: string) => request<AlertEvent>(`/api/v2/alerts/events/${encodeURIComponent(id)}`),
|
||||
actOnAlertV2: (id: string, action: Pick<AlertAction, 'action' | 'note'> & { version: number; actor?: string }) => request<AlertEvent>(`/api/v2/alerts/events/${encodeURIComponent(id)}/actions`, {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(action)
|
||||
}),
|
||||
alertRulesV2: () => request<AlertRule[]>('/api/v2/alerts/rules'),
|
||||
saveAlertRuleV2: (input: AlertRuleInput) => request<AlertRule>(input.version > 0 ? `/api/v2/alerts/rules/${encodeURIComponent(input.id)}` : '/api/v2/alerts/rules', {
|
||||
method: input.version > 0 ? 'PUT' : 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(input)
|
||||
}),
|
||||
setAlertRuleEnabledV2: (id: string, update: { version: number; enabled: boolean; actor?: string }) => request<AlertRule>(`/api/v2/alerts/rules/${encodeURIComponent(id)}/enabled`, {
|
||||
method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(update)
|
||||
}),
|
||||
alertNotificationsV2: (params = new URLSearchParams()) => request<Page<AlertNotification>>(`/api/v2/alerts/notifications?${params.toString()}`),
|
||||
readAlertNotificationsV2: (ids: number[]) => request<{ updated: number }>('/api/v2/alerts/notifications/read', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ids })
|
||||
}),
|
||||
dashboardSummary: () => request<DashboardSummary>('/api/dashboard/summary'),
|
||||
vehicles: (params = new URLSearchParams()) => request<Page<VehicleRow>>(`/api/vehicles?${params.toString()}`),
|
||||
vehicleResolve: (params = new URLSearchParams()) => request<VehicleIdentityResolution>(`/api/vehicles/resolve?${params.toString()}`),
|
||||
vehicleCoverage: (params = new URLSearchParams()) => request<Page<VehicleCoverageRow>>(`/api/vehicles/coverage?${params.toString()}`),
|
||||
vehicleCoverageSummary: (params = new URLSearchParams()) => request<VehicleCoverageSummary>(`/api/vehicles/coverage/summary?${params.toString()}`),
|
||||
vehicleDetail: (params = new URLSearchParams()) => request<VehicleDetail>(`/api/vehicle-service?${params.toString()}`),
|
||||
vehicleProfile: (vin: string) => request<VehicleProfile>(`/api/v2/vehicles/${encodeURIComponent(vin)}/profile`),
|
||||
latestTelemetry: (vin: string) => request<LatestTelemetryResponse>(`/api/v2/vehicles/${encodeURIComponent(vin)}/telemetry/latest`),
|
||||
updateVehicleProfile: (vin: string, input: VehicleProfileInput) => request<VehicleProfile>(`/api/v2/vehicles/${encodeURIComponent(vin)}/profile`, {
|
||||
method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(input)
|
||||
}),
|
||||
syncVehicleProfiles: (input: VehicleProfileSyncRequest) => request<VehicleProfileSyncResult>('/api/v2/vehicle-profiles/sync', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(input)
|
||||
}),
|
||||
vehicleServiceSummary: () => request<VehicleServiceSummary>('/api/vehicle-service/summary'),
|
||||
vehicleServiceOverview: (params = new URLSearchParams()) => request<VehicleServiceOverview>(`/api/vehicle-service/overview?${params.toString()}`),
|
||||
vehicleServiceOverviews: (query: VehicleOverviewBatchQuery) => request<Page<VehicleServiceOverview>>('/api/vehicle-service/overviews', {
|
||||
|
||||
Reference in New Issue
Block a user