diff --git a/src/api/contracts/common.ts b/src/api/contracts/common.ts new file mode 100644 index 0000000..c85c7c4 --- /dev/null +++ b/src/api/contracts/common.ts @@ -0,0 +1,98 @@ +export type ApiErrorCode = + | "VALIDATION_ERROR" + | "PERMISSION_DENIED" + | "NETWORK_ERROR" + | "MAINTENANCE" + | "NOT_FOUND" + | "PARTIAL_FAILURE"; + +export type ApiError = { + code: ApiErrorCode; + message: string; + fields?: Record; +}; + +export type ApiMeta = { + requestId: string; + latencyMs?: number; + pagination?: PaginationMeta; + permissions?: PermissionCheck[]; +}; + +export type ApiResponse = + | { + data: T; + meta: ApiMeta; + error: null; + } + | { + data: null; + meta: ApiMeta; + error: ApiError; + }; + +export type Pagination = { + page: number; + pageSize: number; +}; + +export type PaginationMeta = Pagination & { + total: number; + pageCount: number; +}; + +export type Sort = { + field: string; + direction: "asc" | "desc"; +}; + +export type Filter = { + field: string; + operator: "equals" | "contains" | "startsWith" | "gt" | "lt"; + value: string | number | boolean; +}; + +export type QueryParams = { + search?: string; + pagination?: Pagination; + sort?: Sort; + filters?: Filter[]; +}; + +export type BulkOperation = { + ids: string[]; + operation: string; + payload?: TPayload; +}; + +export type JobProgress = { + id: string; + label: string; + status: "queued" | "running" | "succeeded" | "failed" | "cancelled"; + progress: number; + startedAt: string; + finishedAt?: string; + message?: string; +}; + +export type AuditMetadata = { + actorId: string; + actorName: string; + requestId: string; + ipAddress: string; + userAgent: string; +}; + +export type PermissionCheck = { + permission: string; + allowed: boolean; + reason?: string; +}; + +export type WebSocketEvent = { + id: string; + type: string; + channel: string; + payload: T; + createdAt: string; +};