forked from OurHike/OurHike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.ts
More file actions
106 lines (92 loc) · 4.41 KB
/
Copy pathconfig.ts
File metadata and controls
106 lines (92 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Where published data is fetched from.
//
// The base URL is a build-time variable rather than a constant because the
// bucket it points at is not knowable from the source tree - it is whatever
// R2 (or a local static server, during a field test) is serving
// pipeline/publish.py's output. Set VITE_DATA_BASE_URL at build time; see
// client/README.md.
//
// Keys are flat at the bucket root and must match publish.py's artifact
// names exactly - a mismatch here is a 404 on a mountain, which is why the
// background tier names are spelled the same way in both places.
import type { DetailLevel } from './downloadDetail'
const RAW_BASE: string = import.meta.env.VITE_DATA_BASE_URL ?? ''
export const DATA_BASE_URL = RAW_BASE.replace(/\/+$/, '')
/** False when no bucket was configured at build time, so the UI can say so
* instead of firing downloads at a relative path that will never resolve. */
export const DATA_CONFIGURED = DATA_BASE_URL !== ''
export function dataUrl(key: string): string {
return `${DATA_BASE_URL}/${key}`
}
/** Mirrors publish.py's BACKGROUND_ARCHIVES. */
const BACKGROUND_ARCHIVES: Record<DetailLevel, string> = {
light: 'background_z11.pmtiles',
standard: 'background.pmtiles',
fine: 'background_z13.pmtiles',
}
export function archiveUrl(level: DetailLevel): string {
return dataUrl(BACKGROUND_ARCHIVES[level])
}
/** The same tier as `latest.json` names it - the flat key publish.py uploaded,
* which is what a published hash is looked up by (lib/dataManifest.ts). */
export function archiveKey(level: DetailLevel): string {
return BACKGROUND_ARCHIVES[level]
}
export const TRAILS_KEY = 'trails.geojson'
// Where each blue-blazed spur leads, keyed by the trail id in trails.geojson.
//
// A separate artifact rather than properties on trails.geojson because the
// client stores that file as an opaque Blob and hands it straight to MapLibre
// (lib/trailData.ts) - it never reads a property off it, so enriching it would
// put the answer somewhere the app structurally cannot look.
//
// Published by pipeline/export_spurs.py. Absent from data releases built
// before that existed, which lib/trailData.ts treats as "no spur detail" - not
// as a failed download.
export const SPURS_KEY = 'spurs.json'
// The along-the-trail elevation profile, published by
// pipeline/export_elevation.py: ~141,000 {distance_mi, elevation_ft} samples at
// 25 m spacing along the real centerline. 7.0 MB of JSON that gzips to 0.89 MB,
// measured against the live bucket 2026-08-15 - under 7% of what trails.geojson
// already costs, which is why it is fetched whole rather than windowed.
// Windowing it would also defeat the point: the ribbon has to work in a dead
// zone fifty miles from where it downloaded.
//
// That gzipped figure is only what a hiker actually pays since #717. This
// comment quoted it for a long time while pipeline/publish.py uploaded with no
// Content-Encoding at all, so R2 served every one of the 7.0 MB - a claim about
// a compression nothing was performing.
//
// Absent from data releases built before export_elevation.py existed, which
// lib/trailData.ts treats as "no profile" rather than a failed download - the
// same way spurs.json is treated.
export const ELEVATION_KEY = 'elevation_profile.json'
// 'crossing' is published but is currently an empty FeatureCollection; it is
// listed anyway so it starts working the day the pipeline fills it, rather
// than needing a client release to notice.
//
// This list is the download list, so it is also the size of a hiker's first
// fetch. 'viewpoint', 'parking' and 'privy' roughly double the POI count
// (2,021 more features from ATC's own facility layers) - real weight, and
// still small beside trails.geojson, which at 12.3 MB raw and 4.1 MB gzipped
// (measured 2026-08-15) is the artifact that decides whether a download over a
// hostel's wifi is comfortable. The whole launch fetch is 21.5 MB of text that
// gzips to 5.3 MB, which is what #717 made it cost.
//
// Keep it in step with pipeline/lib/poi_schema.POI_TYPES: verify_release.py
// parses THIS array to know which artifacts a release must serve, so a type
// published but missing here is a layer that silently never reaches a phone.
export const POI_TYPES = [
'shelter',
'water',
'campsite',
'resupply',
'crossing',
'viewpoint',
'parking',
'privy',
] as const
export type PoiType = (typeof POI_TYPES)[number]
export function poiKey(type: PoiType): string {
return `poi_${type}.geojson`
}