import axios from 'axios' export const apiClient = axios.create({ baseURL: import.meta.env.VITE_API_BASE ?? '/api/v1', timeout: 10_000, }) apiClient.interceptors.request.use((config) => { const lang = (typeof navigator !== 'undefined' && navigator.language) || 'ru-RU' config.headers['Accept-Language'] = `${lang},ru-RU;q=0.9,en-US;q=0.8` const token = localStorage.getItem('ordinis.token') if (token) config.headers['Authorization'] = `Bearer ${token}` return config }) apiClient.interceptors.response.use( (resp) => resp, (error) => { if (error.response?.status === 401) { localStorage.removeItem('ordinis.token') } return Promise.reject(error) }, ) export type DataScope = 'PUBLIC' | 'INTERNAL' | 'RESTRICTED' export type DictionaryDefinition = { id: string name: string displayName?: string description?: string scope: DataScope schemaVersion: string bundle: string supportedLocales: string[] defaultLocale: string recordCount?: number createdAt: string updatedAt: string } export type JsonSchema = { $schema?: string type?: string title?: string description?: string properties?: Record required?: string[] enum?: unknown[] format?: string pattern?: string minLength?: number maxLength?: number minimum?: number maximum?: number items?: JsonSchema additionalProperties?: boolean | JsonSchema ['x-localized']?: boolean default?: unknown } export type DictionaryDetail = DictionaryDefinition & { schemaJson: JsonSchema } export type FlattenedRecord = { id: string businessKey: string data: Record dataScope: DataScope validFrom: string validTo: string _meta?: { locale?: string } } export type RecordResponse = { id: string dictionaryId: string businessKey: string data: Record geometryWkt?: string dataScope: DataScope validFrom: string validTo: string createdAt: string updatedAt: string createdBy?: string updatedBy?: string version: number } export type CreateDictionaryRequest = { name: string displayName?: string description?: string scope: DataScope schemaJson: JsonSchema schemaVersion?: string bundle?: string supportedLocales?: string[] defaultLocale?: string } export type CreateRecordRequest = { businessKey: string data: Record geometryWkt?: string validFrom?: string validTo?: string } export type AuditAction = 'CREATE' | 'UPDATE' | 'CLOSE' export type AuditEntry = { id: number eventTime: string eventType: string action: AuditAction | string userId?: string | null userScope?: DataScope | null dictionaryName?: string | null dictionaryId?: string | null recordId?: string | null businessKey?: string | null payloadBefore?: Record | null payloadAfter?: Record | null traceId?: string | null requestId?: string | null ipAddress?: string | null userAgent?: string | null } export type AuditPage = { content: AuditEntry[] totalElements: number totalPages: number number: number size: number first: boolean last: boolean } export type AuditFilters = { dictionaryName?: string userId?: string action?: AuditAction | '' businessKey?: string from?: string to?: string page?: number size?: number } export type OutboxStats = { pending: number; dlq: number } export type DlqEntry = { id: number eventType: string dictionaryName?: string | null aggregateId: string kafkaTopic: string attemptCount: number lastError?: string | null createdAt: string dlqAt: string } export type DlqPage = { content: DlqEntry[] totalElements: number totalPages: number number: number size: number }