osmfeatures 0.2.1 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Official client for the [MapLark OSM Features API](https://maplark.com) to get GeoJSON, FlatGeobuf, GeoParquet, or CSV from OpenStreetMap. The API gets data from dedicated postgis OSM servers separate from public Overpass.
4
4
 
5
- Query OpenStreetMap features such as buildings, streets, and POIs easily. Search for OSM features by bounding box, tags, and geometry shape and get GeoJSON back within less than 250ms (dependent on query size). No converting between formats manually. The API keeps OSM semantics intact, like tags and ways, and returns OSM features you can feed straight into Leaflet, MapLibre, OpenLayers, or any geospatial toolchain. It is backed by postgis with tiered API keys and rate limiting to keep noisy neighbours out to give you low, predictable latency for real traffic. It also has self-host path for those willing to host complex infrastructure themselves.
5
+ Query OpenStreetMap features such as buildings, streets, and POIs easily. Search for OSM features by bounding box, tags, and geometry shape and get GeoJSON back within less than 250ms (dependent on query size). No converting between formats manually. The API keeps OSM semantics intact, like tags and ways, and returns OSM features you can feed straight into Leaflet, MapLibre, OpenLayers, or any geospatial toolchain. It is backed by postgis with tiered API keys and rate limiting to keep noisy neighbours out to give you low, predictable latency for real traffic. It also has a self-host path for those willing to host complex infrastructure themselves, and Geo Agent methods for places search, opening hours, and walk or bike routing.
6
6
 
7
7
  The translation layer is very simple:
8
8
 
@@ -12,11 +12,11 @@ The translation layer is very simple:
12
12
 
13
13
  You filter with the same tags mappers already use (`amenity=cafe`, `building=yes`, and so on). Knowledge from OSM, Overpass, and tagging docs transfers immediately.
14
14
 
15
- To narrow down between "open ways" and "closed ways", use the `shape` parameter:
15
+ To narrow down between "open ways" and "closed ways", use the `way_shape` parameter:
16
16
 
17
- - `shape=line` - open ways (roads, paths, rivers) or line-shaped relations (routes, boundaries)
18
- - `shape=polygon` - closed ways (buildings, parks) or multipolygon relations.
19
- - `shape=all` - both shapes (default when shape is omitted).
17
+ - `way_shape=line` - open ways (roads, paths, rivers) or line-shaped relations (routes, boundaries)
18
+ - `way_shape=polygon` - closed ways (buildings, parks) or multipolygon relations.
19
+ - `way_shape=all` - both shapes (default when way_shape is omitted).
20
20
 
21
21
  For example, to get all buildings in an area:
22
22
 
@@ -102,7 +102,7 @@ Geometric filters such specific OSM element type, min length, or including centr
102
102
  | Param | Type | Default | Description |
103
103
  | ------------ | ---------------------- | ------- | --------------------------------------------------------------------------------------- |
104
104
  | `type` | `string` | all | OSM element types, e.g. `node`, `way`, `relation`, or comma-separated (`way,relation`). |
105
- | `shape` | `line | polygon | all` | `all` | Geometry shape filter for ways and relations. |
105
+ | `wayShape` | `line | polygon | all` | `all` | Geometry class for ways and relations. `shape` is a deprecated alias. |
106
106
  | `centroid` | `boolean` | `false` | When `true`, include a centroid on non-point features. |
107
107
  | `clipGeometry` | `boolean` | `true` | When `true`, clip returned geometry to the requested `bbox`. Set `false` for full geometry. |
108
108
  | `minLengthM` | `number` | | Minimum length in metres (lines). |
@@ -168,7 +168,7 @@ console.log(all.meta.page_count, all.meta.has_more, all.meta.units_charged);
168
168
 
169
169
  ### Params
170
170
 
171
- Same filter params as `query` (`bbox`, `tags`, `orTags`, `notTags`, `type`, `shape`, `zoom`, `location`, `radius`, `osmIds`, `minLengthM`, `maxLengthM`, `minAreaM2`, `maxAreaM2`, `centroid`, `clipGeometry`, `disableBudgetWarning`), plus:
171
+ Same filter params as `query` (`bbox`, `tags`, `orTags`, `notTags`, `type`, `wayShape`, `zoom`, `location`, `radius`, `osmIds`, `minLengthM`, `maxLengthM`, `minAreaM2`, `maxAreaM2`, `centroid`, `clipGeometry`, `disableBudgetWarning`), plus:
172
172
 
173
173
 
174
174
  | Param | Type | Default | Description |
@@ -221,9 +221,37 @@ const usage = await client.usage();
221
221
  console.log(usage.tier, usage.usage_this_month, usage.remaining_this_month);
222
222
  ```
223
223
 
224
- ## `places_search` / `places_nearby` / `places_details`
224
+ ## Geo Agent (places and routes)
225
225
 
226
- Place discovery and lookup. Search is a bbox or `location`+`radius`. Nearby ranks one set from a point. Details refetches a search/nearby feature id (`node/123`). Search and nearby hours use each place's local timezone; optional `asOf` pins the evaluation instant.
226
+ `query()` is the generic OpenStreetMap layer: buildings, roads, park polygons, any tag and geometry shape. Geo Agent is the place and mobility layer on top of the same OSM data. You pick OSM tags (`amenity=cafe`), an area, a time, and walk or bike. The API returns coordinates, opening-hours status, nearest-first ranks, and walk or bike geometry.
227
+
228
+ These endpoints answer questions like "cafes near me", "bars open at 20:00", or "suggest a walking bar crawl in Stockholm". An AI agent or a script can call the same methods.
229
+
230
+ | Endpoint | HTTP | What it does |
231
+ | -------- | ---- | ------------ |
232
+ | `places_search` | `POST /v1/places/search` | Find places in a bounding box **or** a `location` plus `radius`. Filter with OSM tags. Optional `openNow` / `asOf` for opening hours. |
233
+ | `places_nearby` | `POST /v1/places/nearby` | "X near this point". Same tags and hours filters, ranked nearest-first by straight-line distance. |
234
+ | `places_details` | `GET /v1/places/{osm_type}/{osm_id}` | Reload one place by the id search or nearby returned (`node/123`). |
235
+ | `routes_isochrone` | `POST /v1/routes/isochrone` | Walk or bike reach polygon from an origin (how far you can get in N metres or seconds). |
236
+ | `routes_path` | `POST /v1/routes/path` | Walk or bike through stops in the order you list them. No reordering. |
237
+ | `routes_optimized_path` | `POST /v1/routes/optimized_path` | Order the stops for you (a tour from `start`). `loop` (default true) returns to start. |
238
+
239
+ Search and nearby hours use each place's local timezone. Optional `asOf` pins the evaluation instant. Routing is walk or bicycle on the OSM network (`travelMode`: `WALK` or `BICYCLE`). Car routing is not available yet.
240
+
241
+ #### Typical questions
242
+
243
+ | Prompt | SDK |
244
+ |------|-----|
245
+ | "Cafes near me" | `client.places_nearby()` or `client.places_search()` with `location` + `radius` |
246
+ | "Restaurants within 150 m of a station" | two `client.places_search()` calls, then join locally by distance |
247
+ | "Bars open at 20:00" | `client.places_search()` with `asOf`, keep `openingHours.status == "open"` |
248
+ | "Cafes within a 10-minute bike ride" | `client.routes_isochrone()` + `client.places_search()` in a covering radius + keep points inside the polygon |
249
+ | "A walking bar crawl in Stockholm" | `client.places_search()` + `client.routes_optimized_path()` (`loop: true`) |
250
+ | "Walk from my hotel to the cafe, then the office" | `client.routes_path()` with those stops in listed order |
251
+ | "Suggest a walk to a bar, a restaurant, and a cafe, no particular order" | `client.routes_optimized_path()` with `loop: false` |
252
+ | "Is the office a 20-minute walk from the apartment?" | `client.routes_isochrone()` from A, point-in-polygon for B |
253
+
254
+ ### Examples for `places_search` / `places_nearby` / `places_details`
227
255
 
228
256
  ```ts
229
257
  const origin = { lat: 59.316, lon: 18.075 };
@@ -250,9 +278,9 @@ const details = await client.places_details({ osmType: first.id });
250
278
 
251
279
  `places_details` also accepts `{ osmType: 'node', osmId: 123 }`. Hours are annotated at request time in the place's local timezone.
252
280
 
253
- ## `routes_isochrone` / `routes_path` / `routes_optimized_path`
281
+ ### Examples for `routes_isochrone` / `routes_path` / `routes_optimized_path`
254
282
 
255
- Walk or bicycle routing via `POST /v1/routes/*`. Points accept `lon` or `lng`.
283
+ Points accept `lon` or `lng`. `routes_isochrone` takes exactly one of `maxDistanceM` or `durationS`. Optional `searchBufferM` widens the highway fetch corridor.
256
284
 
257
285
  ```ts
258
286
  const origin = { lon: 18.075, lat: 59.316 };
@@ -273,6 +301,4 @@ const tour = await client.routes_optimized_path({
273
301
  });
274
302
  ```
275
303
 
276
- `routes_isochrone` takes exactly one of `maxDistanceM` or `durationS`. `routes_path` follows `stops` in listed order (no TSP). `routes_optimized_path` orders `stops` from `start`; `loop` (default true) returns to start. Optional `searchBufferM` and `travelMode` (`WALK` or `BICYCLE`).
277
-
278
304
  Read the full API reference here [https://maplark.com/developer](https://maplark.com/developer) such as the OpenAPI 2.0 HTTP docs.
package/dist/index.d.ts CHANGED
@@ -32,6 +32,8 @@ export type OSMFeaturesLayer = {
32
32
  orTags?: string[];
33
33
  notTags?: string[];
34
34
  type?: string;
35
+ wayShape?: 'line' | 'polygon' | 'all';
36
+ /** @deprecated Use `wayShape`. */
35
37
  shape?: 'line' | 'polygon' | 'all';
36
38
  };
37
39
  /** Flat query params (same idea as Python `query(**params)`). */
@@ -146,9 +148,9 @@ export declare class OSMFeatures {
146
148
  /** Single HTTP request with retry. Throws on non-OK (same role as Python `_raw_query`). */
147
149
  private _rawQuery;
148
150
  /** Single upstream page. Params map 1:1 to server query string (no tiling). */
149
- query({ bbox, tags, orTags, notTags, type, shape, limit, cursor, zoom, location, radius, osmIds, minLengthM, maxLengthM, minAreaM2, maxAreaM2, disableBudgetWarning, centroid, clipGeometry, accept, }: OSMFeaturesParams, dependencies?: OSMFeaturesDependencies): Promise<OSMFeaturesResult>;
151
+ query({ bbox, tags, orTags, notTags, type, wayShape, shape, limit, cursor, zoom, location, radius, osmIds, minLengthM, maxLengthM, minAreaM2, maxAreaM2, disableBudgetWarning, centroid, clipGeometry, accept, }: OSMFeaturesParams, dependencies?: OSMFeaturesDependencies): Promise<OSMFeaturesResult>;
150
152
  /** Auto-paginate (and optionally tile) until complete. Each page uses `_rawQuery`. */
151
- query_all({ bbox, tags, orTags, notTags, type, shape, zoom, location, radius, osmIds, minLengthM, maxLengthM, minAreaM2, maxAreaM2, disableBudgetWarning, centroid, clipGeometry, accept, limitPerPage, bboxTiles, maxPages, maxFeatures, }: Omit<OSMFeaturesParams, 'limit' | 'cursor'> & {
153
+ query_all({ bbox, tags, orTags, notTags, type, wayShape, shape, zoom, location, radius, osmIds, minLengthM, maxLengthM, minAreaM2, maxAreaM2, disableBudgetWarning, centroid, clipGeometry, accept, limitPerPage, bboxTiles, maxPages, maxFeatures, }: Omit<OSMFeaturesParams, 'limit' | 'cursor'> & {
152
154
  /** Upstream `limit` per HTTP request (page size). */
153
155
  limitPerPage?: number;
154
156
  bboxTiles?: number;
package/dist/index.js CHANGED
@@ -189,8 +189,9 @@ function buildFeaturesQuery(params) {
189
189
  if (params.type) {
190
190
  query.set('type', params.type);
191
191
  }
192
- if (params.shape) {
193
- query.set('shape', params.shape);
192
+ const wayShape = params.wayShape ?? params.shape;
193
+ if (wayShape) {
194
+ query.set('way_shape', wayShape);
194
195
  }
195
196
  for (const tag of params.tags ?? []) {
196
197
  query.append('tags', tag);
@@ -518,13 +519,14 @@ export class OSMFeatures {
518
519
  };
519
520
  }
520
521
  /** Single upstream page. Params map 1:1 to server query string (no tiling). */
521
- async query({ bbox, tags, orTags, notTags, type, shape, limit = DEFAULT_LIMIT, cursor, zoom, location, radius, osmIds, minLengthM, maxLengthM, minAreaM2, maxAreaM2, disableBudgetWarning, centroid, clipGeometry, accept, }, dependencies = {}) {
522
+ async query({ bbox, tags, orTags, notTags, type, wayShape, shape, limit = DEFAULT_LIMIT, cursor, zoom, location, radius, osmIds, minLengthM, maxLengthM, minAreaM2, maxAreaM2, disableBudgetWarning, centroid, clipGeometry, accept, }, dependencies = {}) {
522
523
  const payload = await this._rawQuery({
523
524
  bbox,
524
525
  tags,
525
526
  orTags,
526
527
  notTags,
527
528
  type,
529
+ wayShape,
528
530
  shape,
529
531
  limit,
530
532
  cursor,
@@ -544,7 +546,7 @@ export class OSMFeatures {
544
546
  return payload;
545
547
  }
546
548
  /** Auto-paginate (and optionally tile) until complete. Each page uses `_rawQuery`. */
547
- async query_all({ bbox, tags, orTags, notTags, type, shape, zoom, location, radius, osmIds, minLengthM, maxLengthM, minAreaM2, maxAreaM2, disableBudgetWarning, centroid, clipGeometry, accept, limitPerPage = DEFAULT_LIMIT, bboxTiles = 2, maxPages = 15, maxFeatures = 55_000, }, dependencies = {}) {
549
+ async query_all({ bbox, tags, orTags, notTags, type, wayShape, shape, zoom, location, radius, osmIds, minLengthM, maxLengthM, minAreaM2, maxAreaM2, disableBudgetWarning, centroid, clipGeometry, accept, limitPerPage = DEFAULT_LIMIT, bboxTiles = 2, maxPages = 15, maxFeatures = 55_000, }, dependencies = {}) {
548
550
  if (!isGeojsonAccept(accept)) {
549
551
  throw appError(400, 'invalid_accept', 'query_all only supports GeoJSON; use query({ accept }) for binary encodings.');
550
552
  }
@@ -570,6 +572,7 @@ export class OSMFeatures {
570
572
  orTags,
571
573
  notTags,
572
574
  type,
575
+ wayShape,
573
576
  shape,
574
577
  limit: limitPerPage,
575
578
  zoom,
@@ -670,7 +673,7 @@ export class OSMFeatures {
670
673
  orTags: params.orTags,
671
674
  notTags: params.notTags,
672
675
  type: params.type,
673
- shape: params.shape,
676
+ wayShape: params.wayShape ?? params.shape,
674
677
  limit: params.limit ?? DEFAULT_LIMIT,
675
678
  zoom: params.zoom,
676
679
  location: params.location,
@@ -7,6 +7,8 @@ export type OSMFeaturesLayerPreset = {
7
7
  orTags?: string[];
8
8
  notTags?: string[];
9
9
  type?: string;
10
+ wayShape?: 'line' | 'polygon';
11
+ /** @deprecated Use `wayShape`. */
10
12
  shape?: 'line' | 'polygon';
11
13
  };
12
14
  export declare const OSM_FEATURES_LAYER_PRESETS: Record<OSMFeaturesPresetId, OSMFeaturesLayerPreset>;
@@ -4,14 +4,14 @@ export const OSM_FEATURES_LAYER_PRESETS = {
4
4
  label: 'Buildings',
5
5
  tags: ['building'],
6
6
  type: 'way,relation',
7
- shape: 'polygon',
7
+ wayShape: 'polygon',
8
8
  },
9
9
  roads_paths: {
10
10
  id: 'roads_paths',
11
11
  label: 'Roads & paths',
12
12
  tags: ['highway'],
13
13
  type: 'way,relation',
14
- shape: 'line',
14
+ wayShape: 'line',
15
15
  },
16
16
  parks_green_space: {
17
17
  id: 'parks_green_space',
@@ -37,7 +37,7 @@ export const OSM_FEATURES_LAYER_PRESETS = {
37
37
  'amenity=pub',
38
38
  'amenity=biergarten',
39
39
  ],
40
- shape: 'polygon',
40
+ wayShape: 'polygon',
41
41
  },
42
42
  shops_commerce: {
43
43
  id: 'shops_commerce',
@@ -112,7 +112,7 @@ export const OSM_FEATURES_LAYER_PRESETS = {
112
112
  'waterway=ditch',
113
113
  ],
114
114
  type: 'way,relation',
115
- shape: 'line',
115
+ wayShape: 'line',
116
116
  },
117
117
  };
118
118
  export const OSM_FEATURES_LAYER_PRESET_ORDER = [
@@ -12,6 +12,8 @@ export type ResolvedCustomLayer = {
12
12
  orTags?: string[];
13
13
  notTags?: string[];
14
14
  type?: string;
15
+ wayShape?: 'line' | 'polygon' | 'all';
16
+ /** @deprecated Use `wayShape`. */
15
17
  shape?: 'line' | 'polygon' | 'all';
16
18
  };
17
19
  export type ResolvedDemoLayer = ResolvedPresetLayer | ResolvedCustomLayer;
@@ -24,7 +26,7 @@ export declare function getPreset(id: string): OSMFeaturesLayerPreset | undefine
24
26
  export declare function resolvePresetFromQuery(query: PresetQuery): ResolvedPresetLayer;
25
27
  /**
26
28
  * Custom layer: `tags` / `or_tags` / `not_tags` + required `bbox`.
27
- * Optional `type` / `shape`. Needs at least one positive filter (`tags` or `or_tags`).
29
+ * Optional `type` / `way_shape`. Needs at least one positive filter (`tags` or `or_tags`).
28
30
  */
29
31
  export declare function resolveCustomLayerFromQuery(query: PresetQuery): ResolvedCustomLayer;
30
32
  /**
@@ -91,7 +91,7 @@ export function resolvePresetFromQuery(query) {
91
91
  }
92
92
  /**
93
93
  * Custom layer: `tags` / `or_tags` / `not_tags` + required `bbox`.
94
- * Optional `type` / `shape`. Needs at least one positive filter (`tags` or `or_tags`).
94
+ * Optional `type` / `way_shape`. Needs at least one positive filter (`tags` or `or_tags`).
95
95
  */
96
96
  export function resolveCustomLayerFromQuery(query) {
97
97
  const tags = stringList(query, 'tags');
@@ -114,9 +114,9 @@ export function resolveCustomLayerFromQuery(query) {
114
114
  if (type) {
115
115
  layer.type = type;
116
116
  }
117
- const shape = optionalString(query, 'shape');
118
- if (shape === 'line' || shape === 'polygon' || shape === 'all') {
119
- layer.shape = shape;
117
+ const wayShape = optionalString(query, 'way_shape') ?? optionalString(query, 'shape');
118
+ if (wayShape === 'line' || wayShape === 'polygon' || wayShape === 'all') {
119
+ layer.wayShape = wayShape;
120
120
  }
121
121
  return layer;
122
122
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osmfeatures",
3
- "version": "0.2.1",
3
+ "version": "0.2.4",
4
4
  "description": "Get OpenStreetMap features such as buildings, roads, or points of interest from dedicated servers with a single API call in GeoJSON, FlatGeobuf, Geoparquet, and CSV formats.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,7 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "build": "tsc -p tsconfig.json",
21
- "test": "tsx src/index.test.ts && tsx src/geojson-feature.test.ts && tsx src/preset/preset.test.ts",
21
+ "test": "tsx src/index.test.ts && tsx src/geojson-feature.test.ts && tsx src/preset/preset.test.ts && tsx src/tutorial.test.ts",
22
22
  "prepare": "npm run build",
23
23
  "prepublishOnly": "npm run build"
24
24
  },
@@ -36,7 +36,7 @@
36
36
  "homepage": "https://maplark.com",
37
37
  "repository": {
38
38
  "type": "git",
39
- "url": "https://github.com/MapLark/osmfeatures-typescript.git"
39
+ "url": "https://github.com/MapLark/osmfeatures-ts.git"
40
40
  },
41
41
  "license": "MIT",
42
42
  "engines": {