67 lines
1.9 KiB
TypeScript
67 lines
1.9 KiB
TypeScript
import { loadConfig } from "./configLoader";
|
|
import type { ConfigResult } from "./types";
|
|
|
|
/**
|
|
* Fetch and validate config.json at runtime. The URL is resolved against the
|
|
* app's configured base (import.meta.env.BASE_URL), so it works whether the app
|
|
* is served from a domain root or a subpath.
|
|
*/
|
|
export async function fetchConfig(): Promise<ConfigResult> {
|
|
const url = configUrl();
|
|
|
|
let response: Response;
|
|
try {
|
|
response = await fetch(url.toString(), { cache: "no-cache" });
|
|
} catch (err) {
|
|
return {
|
|
ok: false,
|
|
errors: [`Could not fetch config.json (${describe(err)}).`],
|
|
};
|
|
}
|
|
|
|
if (!response.ok) {
|
|
return {
|
|
ok: false,
|
|
errors: [
|
|
`Could not load config.json (HTTP ${response.status} ${response.statusText}).`,
|
|
],
|
|
};
|
|
}
|
|
|
|
let raw: unknown;
|
|
try {
|
|
raw = await response.json();
|
|
} catch {
|
|
return {
|
|
ok: false,
|
|
errors: ["config.json is not valid JSON."],
|
|
};
|
|
}
|
|
|
|
return loadConfig(raw);
|
|
}
|
|
|
|
/**
|
|
* Resolve the config.json URL for the deployed location. Uses Vite's configured
|
|
* base when it is an absolute path (e.g. "/meal-estimator/"); otherwise falls
|
|
* back to the directory of the current document so a relative "./" base works
|
|
* whether or not the URL has a trailing slash.
|
|
*/
|
|
function configUrl(): string {
|
|
const base = import.meta.env.BASE_URL;
|
|
|
|
if (base.startsWith("/")) {
|
|
// Absolute base path: config sits directly under it.
|
|
return new URL(`${base}config.json`, window.location.origin).toString();
|
|
}
|
|
|
|
// Relative base: resolve against the current document's directory.
|
|
const path = window.location.pathname;
|
|
const dir = path.endsWith("/") ? path : path.slice(0, path.lastIndexOf("/") + 1);
|
|
return new URL(`${dir}config.json`, window.location.origin).toString();
|
|
}
|
|
|
|
function describe(err: unknown): string {
|
|
return err instanceof Error ? err.message : "network error";
|
|
}
|