Files
lonc/src/api/client.js
T

120 lines
2.9 KiB
JavaScript
Raw Normal View History

import { API_PATHS } from '../app/config.js';
function normalizeBaseUrl(baseUrl) {
return baseUrl.trim().replace(/\/+$/, '');
}
function buildUrl({ baseUrl, database, kitchenId, path, query = {}, includeKitchen = true }) {
const cleanBaseUrl = normalizeBaseUrl(baseUrl);
const encodedDatabase = encodeURIComponent(database);
const encodedPath = path.replace(/^\/+/, '');
const kitchenSegment =
includeKitchen && kitchenId
? `/kitchen/${encodeURIComponent(String(kitchenId))}`
: '';
const url = new URL(
`${cleanBaseUrl}/${encodedDatabase}${kitchenSegment}/${encodedPath}`,
);
Object.entries(query).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== '') {
url.searchParams.set(key, String(value));
}
});
return url.toString();
}
async function parseResponse(response) {
const contentType = response.headers.get('content-type') || '';
if (contentType.includes('application/json')) {
return response.json();
}
if (contentType.includes('image/')) {
return response.blob();
}
if (response.status === 204) {
return null;
}
return response.text();
}
function normalizeError(response, payload) {
const message =
payload?.message ||
payload?.error ||
`Request failed with status ${response.status}.`;
return new Error(message, {
cause: {
status: response.status,
details: payload?.errors || payload?.details || null,
},
});
}
export async function apiRequest(store, path, options = {}) {
const { config, session, activeKitchen } = store;
if (!config.baseUrl || !config.database) {
throw new Error('Server URL and database name are required.');
}
const headers = new Headers(options.headers || {});
headers.set('Accept', options.accept || 'application/json');
if (options.body && !options.isFormData) {
headers.set('Content-Type', 'application/json');
}
if (session?.applicationKey) {
headers.set('Authorization', `Bearer ${session.applicationKey}`);
}
const response = await fetch(
buildUrl({
baseUrl: config.baseUrl,
database: config.database,
kitchenId: activeKitchen?.id,
path,
query: options.query,
includeKitchen: options.includeKitchen !== false,
}),
{
method: options.method || 'GET',
headers,
body:
options.body && !options.isFormData
? JSON.stringify(options.body)
: options.body || undefined,
},
);
const payload = await parseResponse(response);
if (!response.ok) {
throw normalizeError(response, payload);
}
return payload;
}
export function getPath(key) {
return API_PATHS[key];
}
export function buildKitchenApiUrl(store, path, query = {}) {
return buildUrl({
baseUrl: store.config.baseUrl,
database: store.config.database,
kitchenId: store.activeKitchen?.id,
path,
query,
includeKitchen: true,
});
}