- Add common generateEncryptedId() utility in @multica/utils - All Device IDs now use same encryption algorithm (40 hex chars) - Web: store encrypted format directly in localStorage - Desktop: use shared utility, accept encrypted ID from Web - Hub: use shared utility for hub-id generation - Telegram: use shared utility for device ID generation - Gateway hook: use encrypted format for client connections Algorithm: sha256(sha256(uuid).slice(0,32)).slice(0,8) + sha256(uuid).slice(0,32) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
73 lines
2.1 KiB
TypeScript
73 lines
2.1 KiB
TypeScript
import { API_HOST } from '@/lib/constant';
|
|
import { getOrCreateDeviceId } from '@/lib/device';
|
|
import { getSid } from '@/lib/auth';
|
|
|
|
// Fetch request wrapper
|
|
export async function request<T = unknown>(url: string, options: RequestInit = {}): Promise<T> {
|
|
// Get or generate Device ID (already encrypted 40-char format)
|
|
let deviceId = '';
|
|
let sid: string | null = null;
|
|
if (typeof window !== 'undefined') {
|
|
deviceId = await getOrCreateDeviceId();
|
|
sid = getSid();
|
|
}
|
|
|
|
const config: RequestInit = {
|
|
...options,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'os-type': '3',
|
|
...(deviceId && { 'Device-Id': deviceId }),
|
|
...(sid && { 'Authorization': `Bearer ${sid}` }),
|
|
...options.headers,
|
|
},
|
|
};
|
|
|
|
const response = await fetch(`${API_HOST}${url}`, config);
|
|
|
|
let data: T;
|
|
const contentType = response.headers.get('content-type');
|
|
if (contentType?.includes('application/json')) {
|
|
data = await response.json();
|
|
} else {
|
|
const text = await response.text();
|
|
data = { message: text || response.statusText } as T;
|
|
}
|
|
|
|
if (!response.ok) {
|
|
console.error('API Error:', {
|
|
status: response.status,
|
|
url,
|
|
data,
|
|
});
|
|
throw new Error(
|
|
(data as { errMsg?: string; message?: string })?.errMsg ||
|
|
(data as { message?: string })?.message ||
|
|
`Request failed with status ${response.status}`
|
|
);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
// GET request
|
|
export function get<T = unknown>(url: string, params?: Record<string, string | number | boolean>) {
|
|
const filteredParams = params
|
|
? Object.fromEntries(
|
|
Object.entries(params).filter(([, v]) => v !== undefined && v !== null)
|
|
)
|
|
: undefined;
|
|
const queryString =
|
|
filteredParams && Object.keys(filteredParams).length > 0
|
|
? `?${new URLSearchParams(filteredParams as Record<string, string>).toString()}`
|
|
: '';
|
|
return request<T>(url + queryString, { method: 'GET' });
|
|
}
|
|
|
|
// POST request
|
|
export function post<T = unknown>(url: string, data?: unknown) {
|
|
return request<T>(url, {
|
|
method: 'POST',
|
|
body: JSON.stringify(data),
|
|
});
|
|
}
|