Fix: resolve data paths against app base for subdirectory deploys
All checks were successful
CI / test-and-build (push) Successful in 48s
All checks were successful
CI / test-and-build (push) Successful in 48s
The static app is served at /maps/ but the data manifest and graph/poi/layer
fetches used absolute /data/... paths, which resolved to the server root and
failed. Add src/lib/base.ts exporting upath() that prefixes a path with the
runtime-detected base (mirroring SvelteKit's 'base: new URL(".", location)'),
and apply it to the manifest, layer, graph and POI fetches. Works at both
root and any sub-path.
This commit is contained in:
parent
8941d837b5
commit
fb6ad3eb0c
27
src/lib/base.ts
Normal file
27
src/lib/base.ts
Normal file
@ -0,0 +1,27 @@
|
||||
// Base-path-aware data URL resolution for the Navigator static app.
|
||||
//
|
||||
// The app is built with the static adapter and deployed to a subdirectory
|
||||
// (e.g. /maps/). Its built index.html auto-detects the base from location
|
||||
// (base: new URL(".", location)), so all internal asset/data fetches must be
|
||||
// prefixed with that same base. Data manifest paths are stored as absolute
|
||||
// (/data/...) by the build scripts, so we resolve them against the running
|
||||
// location rather than the server root.
|
||||
//
|
||||
// E.g. served at https://site/maps/ -> base '/maps'; the manifest path
|
||||
// '/data/_index.json' becomes '/maps/data/_index.json'.
|
||||
|
||||
export function appBase(): string {
|
||||
if (typeof window === 'undefined') return '';
|
||||
// Mirror the SvelteKit runtime detection: base = directory of the current
|
||||
// page, with the trailing slash removed (so '/' -> '', '/maps/' -> '/maps').
|
||||
const dir = new URL('.', window.location.href).pathname;
|
||||
return dir.replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
// Resolve a path that may be absolute ('/data/x.json') relative to the app's
|
||||
// base. Leaves already-relative and non-leading-slash/dotted paths untouched.
|
||||
export function upath(p: string): string {
|
||||
if (!p) return p;
|
||||
if (p.startsWith('/')) return appBase() + p;
|
||||
return p;
|
||||
}
|
||||
@ -9,6 +9,7 @@
|
||||
import { prefs } from '$lib/prefs';
|
||||
import type { RouteGraph, AvoidRule, RouteResult } from '$lib/routing';
|
||||
import { savedPoints, addSavedPoint, removeSavedPoint, exportSavedPoints, importSavedPoints, type SavedPoint } from '$lib/savedPoints';
|
||||
import { upath } from '$lib/base';
|
||||
|
||||
type FeatureCollection = {
|
||||
type: string;
|
||||
@ -184,7 +185,7 @@
|
||||
if (!layer || !layer.graphPath || !layer.poiPath) { routeGraph = null; hasRouteGraph = false; return; }
|
||||
routeLoading = true;
|
||||
try {
|
||||
const [g, p] = await Promise.all([fetch(layer.graphPath), fetch(layer.poiPath)]);
|
||||
const [g, p] = await Promise.all([fetch(upath(layer.graphPath)), fetch(upath(layer.poiPath))]);
|
||||
if (!g.ok) throw new Error(`graph HTTP ${g.status}`);
|
||||
if (!p.ok) throw new Error(`poi HTTP ${p.status}`);
|
||||
routeGraph = await g.json();
|
||||
@ -420,7 +421,7 @@
|
||||
try {
|
||||
for (const layer of layers) {
|
||||
try {
|
||||
const res = await fetch(layer.path);
|
||||
const res = await fetch(upath(layer.path));
|
||||
if (!res.ok) throw new Error(`fetch ${layer.path}: HTTP ${res.status}`);
|
||||
const fc: FeatureCollection = await res.json();
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import MapView, { type MapLayer } from '$lib/components/MapView.svelte';
|
||||
import { upath } from '$lib/base';
|
||||
|
||||
type AreaManifest = MapLayer;
|
||||
|
||||
@ -10,7 +11,7 @@
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
const res = await fetch('/data/_index.json');
|
||||
const res = await fetch(upath('/data/_index.json'));
|
||||
if (!res.ok) throw new Error(`manifest HTTP ${res.status}`);
|
||||
areas = (await res.json()) as MapLayer[];
|
||||
} catch (e) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user