5180 fichiers 38.5 Mo 0 téléchargements 199 vues mis à jour il y a 5 heures ui
nitro-v36-with-renderer-v36 / src / api / housekeeping / HousekeepingHttpClient.ts
HousekeepingHttpClient.ts 3.5 Ko Télécharger le fichier
import { getAccessToken } from '../auth/accessToken';

const trimSlash = (value: string) => value.replace(/\/$/, '');

const resolveBaseUrl = (): string => {
    const mode = (window as any).OctaneClientMode;

    if (mode && typeof mode.apiBaseUrl === 'string' && mode.apiBaseUrl.length) return trimSlash(mode.apiBaseUrl);

    const configured = (window as any).OctaneSecureApiUrl;

    if (typeof configured === 'string' && configured.length) return trimSlash(configured);

    return trimSlash(window.location.origin);
};

const buildUrl = (path: string): string => {
    const base = resolveBaseUrl();
    const normalized = path.startsWith('/') ? path : `/${path}`;

    return `${base}${normalized}`;
};

const authHeader = (): Record<string, string> => {
    const token = getAccessToken();

    return token ? { Authorization: `Bearer ${token}` } : {};
};

export interface HousekeepingRequestInit {
    method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
    body?: unknown;
    query?: Record<string, string | number | boolean | undefined | null>;
    signal?: AbortSignal;
}

const appendQuery = (url: string, query?: HousekeepingRequestInit['query']): string => {
    if (!query) return url;

    const params = new URLSearchParams();

    for (const [key, value] of Object.entries(query)) {
        if (value === undefined || value === null) continue;

        params.set(key, String(value));
    }

    const qs = params.toString();

    return qs.length ? `${url}?${qs}` : url;
};

/**
 * Thin HTTP wrapper for the admin/housekeeping endpoints. Backed by the
 * same `apiBaseUrl` the secure-asset layer uses, with the user's
 * persisted access token attached as a bearer.
 *
 * Server is expected to expose REST endpoints under
 * `${apiBaseUrl}/api/housekeeping/...`. The shape mirrors what
 * Arcturus-style admin panels already publish, so a server-side
 * implementation is incremental rather than greenfield.
 */
export const housekeepingFetch = async <T = unknown>(path: string, init: HousekeepingRequestInit = {}): Promise<T> => {
    const { method = 'GET', body = undefined, query = undefined, signal = undefined } = init;
    const url = appendQuery(buildUrl(path), query);

    const response = await fetch(url, {
        method,
        signal,
        headers: {
            'Content-Type': 'application/json',
            Accept: 'application/json',
            ...authHeader()
        },
        body: body !== undefined ? JSON.stringify(body) : undefined,
        credentials: 'include'
    });

    if (!response.ok) {
        let detail = '';

        try {
            const text = await response.text();
            detail = text || '';
        } catch {}

        throw new HousekeepingHttpError(response.status, response.statusText, detail, url);
    }

    if (response.status === 204) return undefined;

    const contentType = response.headers.get('content-type') || '';

    if (!contentType.includes('application/json')) return undefined;

    return await response.json();
};

export class HousekeepingHttpError extends Error {
    public readonly status: number;
    public readonly statusText: string;
    public readonly detail: string;
    public readonly url: string;

    constructor(status: number, statusText: string, detail: string, url: string) {
        super(`HK HTTP ${status} ${statusText}: ${detail || url}`);
        this.name = 'HousekeepingHttpError';
        this.status = status;
        this.statusText = statusText;
        this.detail = detail;
        this.url = url;
    }
}
15Sujets
1Dépôts
20Membres
2En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser