Client libraries¶
Two thin clients, one API, one name: geoworld on
PyPI and on
npm. They ship no data. Each reads
data/index.json from a pinned data release,
downloads the files you ask for, caches them and verifies their sha256
against the index.
Both are documented in full on their own pages: Python and JavaScript. Three adapters put the JavaScript client on a map or in a component tree: MapLibre, Leaflet and React.
| Package | What it is | Runtime deps |
|---|---|---|
geoworld (PyPI) |
Python client | none |
geoworld (npm) |
JavaScript/TypeScript client | none |
geoworld-maplibre |
addBoundaries, feature state by stable id, fitToBounds |
none (maplibre-gl peer) |
geoworld-leaflet |
withLeaflet(L).addBoundaries, layerById, toLatLngBounds |
none (leaflet optional peer) |
geoworld-react |
GeoWorldProvider, useBoundaries, useCountry, useChildren, … |
none (react peer) |
What they do — and do not do¶
- Read the index once.
data/index.jsonlists every territory, level, file, size, checksum and licence.countries(),levels(),bbox()andurl()answer from it without downloading any GeoJSON. - Download on demand.
get()fetches one level of one territory. Levels too big for a single file (Brazil's municipalities) come as parts, one per first-level division:get_part()/getPart()anditer_parts()/iterParts(). - Cache. Python writes to the platform cache directory; JavaScript keeps
files in memory and, in Node, can persist them with
geoworld/node. The layout is the same,geoworld/<version>/<path>, so the two can share a directory. - Verify. Every full-resolution file is hashed after download and every cached read is re-hashed; a mismatch is an error, never silently used.
- Navigate. Every feature has a stable
idand every sub-national feature aparentID, sofind(),parent(),children()andsearch()work across levels without matching on names. - Nothing server-side. The libraries talk to static files —
raw.githubusercontent.comat the release tag by default, or any host you pointbase_url/baseUrlat, including a local directory or an unzipped release asset.
They are not a GIS: no reprojection, no geometry operations, no rendering.
Hand the FeatureCollection to GeoPandas, Leaflet, MapLibre or whatever you
already use. (to_geopandas() exists in Python as a convenience.)
The same API in both¶
| Python | JavaScript | Returns |
|---|---|---|
GeoWorld(version, base_url=, cache_dir=, cache=, verify=) |
createClient({ version, baseUrl, cache, fetch, verify }) |
a client |
index() |
index() |
the whole index.json |
countries() |
countries() |
one summary per territory |
country(iso3) |
country(iso3) |
the full index entry |
levels(iso3) |
levels(iso3) |
["ADM0", "ADM1", …] |
dataset(iso3, level) |
dataset(iso3, level) |
the index entry of one level |
bbox(iso3, level) |
bbox(iso3, level) |
[west, south, east, north] |
parts(iso3, level) |
parts(iso3, level) |
part codes of a split level |
url(iso3, level, part=, preview=) |
url(iso3, level, { part, preview }) |
the file's URL |
get(iso3, level) |
get(iso3, level) |
FeatureCollection |
get_part(iso3, level, code) |
getPart(iso3, level, code) |
FeatureCollection |
iter_parts(iso3, level) |
iterParts(iso3, level) |
(code, FeatureCollection) pairs |
features(iso3, level) |
features(iso3, level) |
every feature, across parts if needed |
preview(iso3, level) |
preview(iso3, level) |
the simplified FeatureCollection |
find(id) |
find(id) |
one Feature |
parent(id) |
parent(id) |
the parent Feature, or none |
children(id) |
children(id) |
Features of the next level |
search(text, iso3, level=) |
search(text, iso3, level?) |
matching Features |
clear_cache() |
clearCache() |
— |
to_geopandas(iso3, level) |
— | a GeoDataFrame |
Everything in JavaScript is async. Errors are typed the same way on both
sides (UnknownCountry, UnknownLevel, NoCombinedFile, ChecksumMismatch,
UnsupportedSchema, …) and all extend GeoWorldError.
Both clients are tested against the same fixtures and must produce the same
fixtures/expected/fixtures.json byte for byte, so what one computes the other
computes too.
Versions¶
The libraries' versions and the data's versions are independent
(why). Each library release
declares the data schema_version it understands and a default data release:
| Library | Default data | Supports schema | |
|---|---|---|---|
| Python | geoworld 0.1.0 |
1.0.0 |
1 |
| JavaScript | geoworld 0.2.0, and the three adapters at the same version |
1.0.0 |
1 |
The JavaScript packages move in lockstep: one version number, one tag, and
each adapter declares geoworld as a peer at that minor.
Pin the data version you tested against. version="main" works for
experiments but warns: the branch moves, and nothing is cached on disk.
Releasing¶
Maintainers publish from tags: python-vX.Y.Z runs publish-python.yml
(PyPI, trusted publishing) and js-vX.Y.Z runs publish-js.yml, which
publishes geoworld and then the three adapters with provenance, skipping
any of them already on the registry at that version. Both workflows refuse a
tag that does not match the versions in the packages.