feat(api): /devices register + paseto v4 (middleware Bearer, bootstrap mobile du token)

This commit is contained in:
m
2026-09-10 07:25:11 +02:00
parent bdf1fadce9
commit caa6e6483c
18 changed files with 407 additions and 27 deletions
+24
View File
@@ -1,6 +1,7 @@
import type {
ApiData,
ApiErrorBody,
DeviceRegistration,
FileDto,
FolderDto,
ListFilesParams,
@@ -11,6 +12,12 @@ const API_BASE_URL = process.env.EXPO_PUBLIC_API_BASE_URL ?? 'http://localhost:8
export const DEFAULT_TIMEOUT_MS = 15_000;
let authToken: string | null = null;
export function setAuthToken(token: string | null): void {
authToken = token;
}
type QueryParams = Record<string, string | number | boolean | undefined | null>;
function toQuery(params?: QueryParams): string {
@@ -24,6 +31,15 @@ function toQuery(params?: QueryParams): string {
return query ? `?${query}` : '';
}
function mergeHeaders(init?: HeadersInit): HeadersInit | undefined {
if ( !authToken ) return init;
const merged = new Headers(init);
if ( !merged.has('Authorization') ) {
merged.set('Authorization', `Bearer ${authToken}`);
}
return merged;
}
export class ApiError extends Error {
readonly code: string;
@@ -46,6 +62,7 @@ async function request<T>(
try {
response = await fetch(`${API_BASE_URL}${path}`, {
...init,
headers: mergeHeaders(init.headers),
signal: controller.signal,
});
} catch {
@@ -76,6 +93,13 @@ export const api = {
health: () => request<{ status: string }>('/health'),
registerDevice: (deviceId: string) =>
request<DeviceRegistration>('/devices', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ deviceId }),
}),
listFiles: (params?: ListFilesParams) =>
request<FileDto[]>(`/files${toQuery(params)}`),
+5
View File
@@ -42,6 +42,11 @@ export type OcrJob = {
error?: string | null;
};
export type DeviceRegistration = {
deviceId: string;
token: string;
};
export type ListParams = {
page?: number;
pageSize?: number;