chiitiler 1.20.1 → 1.20.3

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
@@ -1,285 +1,164 @@
1
- # chiitiler – Lightweight Raster Tile Server for MapLibre Style
1
+ <div align="center">
2
2
 
3
- ![GitHub Release](https://img.shields.io/github/v/release/Kanahiro/chiitiler?label=ghcr.io/kanahiro/chiitiler)
4
- ![Unit Tests](https://img.shields.io/github/actions/workflow/status/Kanahiro/chiitiler/test:unit.yml?label=unit%20tests)
5
- ![Integration Tests](https://img.shields.io/github/actions/workflow/status/Kanahiro/chiitiler/test:integration.yml?label=integration)
6
- [![codecov](https://codecov.io/gh/Kanahiro/chiitiler/graph/badge.svg?token=9RVLAJG126)](https://codecov.io/gh/Kanahiro/chiitiler)
7
-
8
- ![chiitiler logo](./logo.webp)
9
-
10
- > Chiitiler is a tiny MapLibre server that renders raster tiles and map cut-outs from any MapLibre Style JSON, with built-in caching backends for source assets and a lightweight debug UI.
11
-
12
- ## Overview
13
-
14
- Chiitiler accepts remote or local `style.json` definitions and serves raster tiles or bounding-box images on demand. It was inspired by [`maptiler/tileserver-gl`](https://github.com/maptiler/tileserver-gl) and [`developmentseed/titiler`](https://github.com/developmentseed/titiler) but is intentionally minimal, scriptable, and easy to self-host.
3
+ <img src="./logo.svg" alt="chiitiler" width="200" />
15
4
 
16
- ### Highlights
5
+ # chiitiler
17
6
 
18
- - Zero-config startup: point Chiitiler at a style URL or POST a style object to receive tiles.
19
- - Optimized for ephemeral serverless runtimes such as AWS Lambda.
20
- - Multiple cache adapters (`memory`, `file`, `s3`, `gcs`) to cache shared source assets (MVT tiles, glyphs, sprites) and reduce redundant fetches.
21
- - Built-in `/debug` and `/editor` pages to preview styles during development.
7
+ **A tiny raster tile server for MapLibre styles.**
22
8
 
23
- ### In Production
9
+ Point it at any `style.json` and get back PNG / WebP / JPEG tiles, static images, or map cut-outs.
24
10
 
25
- - [MIERUNE/tiles](https://github.com/MIERUNE/tiles) – see the live example [map](https://mierune.github.io/tiles/color.html#11.62/43.064/141.3375).
26
- - [dayjournal/qgis-amazonlocationservice-plugin](https://github.com/dayjournal/qgis-amazonlocationservice-plugin) – powering QGIS integrations.
27
- - [PLATEAU VIEW](https://plateauview.mlit.go.jp/) – serving Cesium.js imagery through the `/tiles` endpoint.
28
- - [Allmaps Latest (Bluesky)](https://bsky.app/profile/latest.allmaps.org).
29
-
30
- ## Supported Data Protocols
31
-
32
- Chiitiler can load tiles, sprites, glyphs, and assets via:
33
-
34
- - `http://` and `https://`
35
- - `s3://` (AWS S3 or compatible endpoints)
36
- - `gs://` (Google Cloud Storage)
37
- - `file://`
38
- - `mbtiles://`
39
- - `pmtiles://`
40
- - `cog://` (Cloud Optimized GeoTIFF, CRS must be `EPSG:3857`)
41
-
42
- ## Project Layout
11
+ [![Release](https://img.shields.io/github/v/release/Kanahiro/chiitiler?label=ghcr.io%2Fkanahiro%2Fchiitiler&color=0ea5e9)](https://github.com/Kanahiro/chiitiler/pkgs/container/chiitiler)
12
+ [![Unit Tests](https://img.shields.io/github/actions/workflow/status/Kanahiro/chiitiler/test:unit.yml?label=unit)](https://github.com/Kanahiro/chiitiler/actions)
13
+ [![Integration](https://img.shields.io/github/actions/workflow/status/Kanahiro/chiitiler/test:integration.yml?label=integration)](https://github.com/Kanahiro/chiitiler/actions)
14
+ [![codecov](https://codecov.io/gh/Kanahiro/chiitiler/graph/badge.svg?token=9RVLAJG126)](https://codecov.io/gh/Kanahiro/chiitiler)
15
+ [![License](https://img.shields.io/github/license/Kanahiro/chiitiler?color=blue)](./LICENSE)
43
16
 
44
- ```
45
- src/
46
- main.ts # CLI entry point and cluster bootstrap
47
- cli.ts # Commander-based CLI definition
48
- server/ # Hono HTTP server & debug UI
49
- render/ # Rasterization and Sharp pipelines
50
- cache/ # Cache adapters (none/memory/file/s3/gcs)
51
- source/ # Helpers for reading external sources
52
- tests/ # Vitest integration & benchmark suites
53
- localdata/ # Sample styles and tiles for demos
54
- cdk/ # AWS CDK deployment project
55
- ```
17
+ [Quickstart](#quickstart) · [HTTP API](#http-api) · [Library](#library-usage) · [Deployment](#deployment)
56
18
 
57
- ## Quick Start
19
+ </div>
58
20
 
59
- ### Requirements
21
+ ---
60
22
 
61
- - Node.js 24.12.0 or newer (`.node-version` is provided).
62
- - System dependencies to support `sharp` (see [Dockerfile](./Dockerfile) for reference).
23
+ ## From zero to a rendered tile in 30 seconds
63
24
 
64
- ### Run From Source
25
+ **1. Run the server** — one command, no config file, no database, no API key.
65
26
 
66
27
  ```bash
67
- git clone https://github.com/Kanahiro/chiitiler.git
68
- cd chiitiler
69
- npm install
70
- npx tsx src/main.ts tile-server --port 3000 --debug
28
+ docker run --rm -p 3000:3000 ghcr.io/kanahiro/chiitiler:latest
71
29
  ```
72
30
 
73
- When the server starts you can request a tile:
31
+ **2. Open a tile in your browser** pass any MapLibre style URL as `?url=`.
74
32
 
75
33
  ```
76
34
  http://localhost:3000/tiles/0/0/0.png?url=https://tile.openstreetmap.jp/styles/osm-bright/style.json
77
35
  ```
78
36
 
79
- ### Docker Image
37
+ You're done. That same endpoint works as an XYZ tile source for Leaflet, MapLibre, OpenLayers, QGIS, Cesium, or anywhere else that speaks `{z}/{x}/{y}`.
80
38
 
81
- ```bash
82
- docker pull ghcr.io/kanahiro/chiitiler:latest
83
- docker run --rm -p 3000:3000 \
84
- -e CHIITILER_CACHE_METHOD=memory \
85
- -e CHIITILER_CACHE_TTL_SEC=600 \
86
- ghcr.io/kanahiro/chiitiler:latest
87
- ```
88
-
89
- The container entrypoint wraps `node /app/build/main.cjs tile-server`, so command-line options can be provided via env vars or by overriding the container CMD explicitly.
39
+ > **No Docker?** `npx tsx` works too:
40
+ > ```bash
41
+ > git clone https://github.com/Kanahiro/chiitiler && cd chiitiler && npm i
42
+ > npx tsx src/main.ts tile-server --debug
43
+ > ```
44
+ > Then visit `http://localhost:3000/debug` to preview styles interactively.
90
45
 
91
- #### docker-compose (local S3 + GCS emulation)
46
+ ## Features
92
47
 
93
- The included [`docker-compose.yml`](./docker-compose.yml) spins up MinIO and `fake-gcs-server`:
48
+ - **Zero-config** — no config file, no YAML, no database. Just a style URL.
49
+ - **Works with any MapLibre style** — remote URL or `POST` the JSON inline
50
+ - **Multiple outputs** — slippy tiles (`/tiles`), bounding-box clips (`/clip`), free-form camera shots (`/camera`)
51
+ - **Serverless-friendly** — small footprint, runs on AWS Lambda via Web Adapter (see [`cdk/`](./cdk))
52
+ - **Pluggable caching** — `memory` · `file` · `s3` · `gcs` backends for shared source assets
53
+ - **Many protocols** — `http(s)` · `s3` · `gs` · `file` · `mbtiles` · `pmtiles` · `cog`
54
+ - **Library or server** — import the renderer directly into your Node.js pipeline
55
+ - **Built-in debug UI** — `/debug` and `/editor` for live style preview
94
56
 
95
- ```bash
96
- docker compose up
97
- ```
57
+ ## In Production
98
58
 
99
- Volumes mount `localdata/` and `.cache/` so test assets and cached source data persist between runs.
59
+ - **[MIERUNE/tiles](https://github.com/MIERUNE/tiles)** [live example](https://mierune.github.io/tiles/color.html#11.62/43.064/141.3375)
60
+ - **[PLATEAU VIEW](https://plateauview.mlit.go.jp/)** — Cesium.js imagery via `/tiles`
61
+ - **[qgis-amazonlocationservice-plugin](https://github.com/dayjournal/qgis-amazonlocationservice-plugin)** — QGIS integration
62
+ - **[Allmaps Latest](https://bsky.app/profile/latest.allmaps.org)** — Bluesky bot
100
63
 
101
64
  ## HTTP API
102
65
 
103
- | Method | Path Pattern | Description |
104
- | ------ | ------------ | ----------- |
105
- | GET/POST | `/tiles/{z}/{x}/{y}.{ext}` | Render a raster tile (`png`, `jpeg`, `jpg`, `webp`). |
106
- | GET/POST | `/clip.{ext}` | Render a bounding box image (`png`, `jpeg`, `jpg`, `webp`). |
107
- | GET/POST | `/camera/{zoom}/{lat}/{lon}/{bearing}/{pitch}/{width}x{height}.{ext}` | Render a static image (`png`, `jpeg`, `jpg`, `webp`). |
108
- | GET | `/debug` | Style explorer UI (requires debug mode). |
109
- | GET | `/editor` | Lightweight style editor (requires debug mode). |
66
+ | Method | Endpoint | Description |
67
+ | --- | --- | --- |
68
+ | `GET` / `POST` | `/tiles/{z}/{x}/{y}.{ext}` | Slippy-map raster tile |
69
+ | `GET` / `POST` | `/clip.{ext}` | Bounding-box cut-out |
70
+ | `GET` / `POST` | `/camera/{zoom}/{lat}/{lon}/{bearing}/{pitch}/{width}x{height}.{ext}` | Free-form camera shot |
71
+ | `GET` | `/debug`, `/editor` | Debug UI (requires `--debug`) |
110
72
 
111
- ### Query Parameters
73
+ `ext` is one of `png`, `jpeg`, `jpg`, `webp`.
112
74
 
113
- - `url` – Required when using GET. Points to a MapLibre Style JSON.
114
- - `tileSize` – Tile size in pixels (default `512`).
115
- - `quality` – JPEG/WebP quality (default `100`).
116
- - `margin` – Tile edge margin (default `0`).
117
- - `bbox` – Bounding box for `/clip` as `minLon,minLat,maxLon,maxLat`.
118
- - `size` – Longest edge of `/clip` output (default `1024`).
75
+ **Query parameters**
119
76
 
120
- POST requests accept the style object directly in the JSON body (`{ "style": { ... } }`).
77
+ | Name | Default | Notes |
78
+ | --- | --- | --- |
79
+ | `url` | — | Style JSON URL (required for `GET`) |
80
+ | `tileSize` | `512` | Tile size in pixels |
81
+ | `quality` | `100` | JPEG / WebP quality |
82
+ | `margin` | `0` | Tile edge margin |
83
+ | `bbox` | — | `/clip` bounding box: `minLon,minLat,maxLon,maxLat` |
84
+ | `size` | `1024` | `/clip` longest edge in pixels |
121
85
 
122
- ## CLI Reference
123
-
124
- Chiitiler exposes a single command: `tile-server`.
125
-
126
- ```bash
127
- npx tsx src/main.ts tile-server --help
128
- ```
129
-
130
- | Option | Description | Environment Fallback | Default |
131
- | ------ | ----------- | -------------------- | ------- |
132
- | `--cache <none/memory/file/s3/gcs>` | Select cache backend. | `CHIITILER_CACHE_METHOD` | `none` |
133
- | `--cache-ttl <seconds>` | TTL for memory/file caches. | `CHIITILER_CACHE_TTL_SEC` | `3600` |
134
- | `--memory-cache-max-item-count <n>` | Max items in memory cache. | `CHIITILER_MEMORYCACHE_MAXITEMCOUNT` | `1000` |
135
- | `--file-cache-dir <dir>` | Disk cache directory. | `CHIITILER_FILECACHE_DIR` | `./.cache` |
136
- | `--s3-cache-bucket <name>` | S3 bucket for caching. | `CHIITILER_S3CACHE_BUCKET` | `""` |
137
- | `--s3-region <region>` | S3 region used for requests. | `CHIITILER_S3_REGION` | `us-east-1` |
138
- | `--s3-endpoint <url>` | S3-compatible endpoint. | `CHIITILER_S3_ENDPOINT` | `""` |
139
- | `--s3-force-path-style` | Force path-style requests. | `CHIITILER_S3_FORCE_PATH_STYLE` (`true/false`) | `false` |
140
- | `--gcs-cache-bucket <name>` | GCS bucket for caching. | `CHIITILER_GCS_CACHE_BUCKET` | `""` |
141
- | `--gcs-project-id <id>` | GCP project ID. | `CHIITILER_GCS_PROJECT_ID` | `""` |
142
- | `--gcs-key-filename <path>` | Service account JSON. | `CHIITILER_GCS_KEY_FILENAME` | `""` |
143
- | `--gcs-cache-prefix <prefix>` | GCS object prefix. | `CHIITILER_GCS_CACHE_PREFIX` | `""` |
144
- | `--gcs-api-endpoint <url>` | Custom GCS endpoint. | `CHIITILER_GCS_API_ENDPOINT` | `""` |
145
- | `--port <number>` | HTTP listen port. | `CHIITILER_PORT` | `3000` |
146
- | `--debug` | Enable debug UI routes. | `CHIITILER_DEBUG` | `false` |
147
-
148
- Set `CHIITILER_PROCESSES` to control clustering (`0` uses all CPUs). When `>1`, the primary process forks workers that all share the same cache adapter.
149
-
150
- ## Environment Variables
151
-
152
- In addition to the CLI options above, the server respects:
153
-
154
- | Variable | Default | Notes |
155
- | -------- | ------- | ----- |
156
- | `CHIITILER_PROCESSES` | `1` | Number of worker processes; `0` = `availableParallelism()`. |
157
- | `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | – | Used by the S3 cache adapter. |
158
- | `AWS_REGION` | – | Overrides SDK default region if set. |
159
- | `GOOGLE_APPLICATION_CREDENTIALS` | – | Path to a service account JSON used by the GCS adapter. |
160
-
161
- ## Cache Backends
162
-
163
- Chiitiler caches the source material required for rendering (vector tiles, glyphs, sprites, spritesheets), not the final raster outputs. These cached assets are reused across requests to avoid refetching upstream sources.
164
-
165
- - **none** – No caching; every request renders from scratch.
166
- - **memory** – In-memory LRU cache with configurable TTL and max entries.
167
- - **file** – Stores fetched source assets under `CHIITILER_FILECACHE_DIR`.
168
- - **s3** – Uploads cached source assets to S3/MinIO; honors custom endpoint and path-style.
169
- - **gcs** – Uploads cached source assets to Google Cloud Storage or `fake-gcs-server`.
170
-
171
- Each adapter exposes the same `get`/`set` interface and can be reused when embedding Chiitiler as a library.
172
-
173
- ## Debug Tools
174
-
175
- Run with `--debug` or `CHIITILER_DEBUG=true` to unlock:
176
-
177
- - `/debug` – Inspect styles, test queries, and view response metadata.
178
- - `/editor` – Lightweight MapLibre style editor with live preview.
179
-
180
- ## Development & Testing
181
-
182
- ```bash
183
- npm run dev # Watch mode via tsx
184
- npm run build # Bundle to build/main.cjs with esbuild
185
- npm run test:unit # Vitest unit suite (src/**/*.test.ts)
186
- npm run test:integration # End-to-end scenarios in tests/
187
- npm run test:coverage # Unit coverage with V8 provider
188
- npm run test:benchmark # Performance tests (see BENCHMARK.md)
189
- ```
190
-
191
- Benchmark scenarios and recent measurements live in [BENCHMARK.md](./BENCHMARK.md).
86
+ For `POST`, send the style object as JSON body: `{ "style": { ... } }`.
192
87
 
193
88
  ## Library Usage
194
89
 
195
- Chiitiler is also published as an npm library. Core helpers return Sharp instances or encoded buffers so you can integrate the renderer into other pipelines.
90
+ Chiitiler is also published to npm. Returns `Buffer` or `Sharp` streams.
196
91
 
197
92
  ```ts
198
- import {
199
- getRenderedTileBuffer,
200
- getRenderedClipBuffer,
201
- getRenderedCameraBuffer,
202
- getRenderedTileStream,
203
- getRenderedClipStream,
204
- getRenderedCameraStream,
205
- ChiitilerCache,
206
- } from 'chiitiler';
93
+ import { getRenderedTileBuffer, ChiitilerCache } from 'chiitiler';
207
94
 
208
95
  const cache = ChiitilerCache.fileCache({ dir: './.cache', ttl: 3600 });
209
96
 
210
- const tile = await getRenderedTileBuffer({
97
+ const png = await getRenderedTileBuffer({
211
98
  stylejson: 'https://tile.openstreetmap.jp/styles/osm-bright/style.json',
212
- z: 5,
213
- x: 27,
214
- y: 12,
99
+ z: 5, x: 27, y: 12,
215
100
  tileSize: 512,
216
- margin: 0,
217
- ext: 'webp',
101
+ ext: 'png',
218
102
  quality: 100,
103
+ margin: 0,
219
104
  cache,
220
105
  });
106
+ ```
221
107
 
222
- const clip = await getRenderedClipBuffer({
223
- stylejson: 'file://localdata/style.json',
224
- bbox: [123.4, 34.5, 124.5, 35.6],
225
- size: 1024,
226
- ext: 'png',
227
- quality: 95,
228
- cache: ChiitilerCache.noneCache(),
229
- });
108
+ Available renderers: `getRenderedTileBuffer`, `getRenderedClipBuffer`, `getRenderedCameraBuffer`, and their `*Stream` variants (`Sharp` instances for further piping).
230
109
 
231
- const camera = await getRenderedCameraBuffer({
232
- stylejson: 'file://localdata/style.json',
233
- center: [139.69, 35.68],
234
- zoom: 10,
235
- bearing: 180,
236
- pitch: 60,
237
- width: 1024,
238
- height: 1024,
239
- ext: 'png',
240
- quality: 95,
241
- cache,
242
- });
110
+ ## Configuration
243
111
 
244
- // you can get Sharp streams directly
245
- const tileStream = await getRenderedTileStream({
246
- stylejson: 'https://tile.openstreetmap.jp/styles/osm-bright/style.json',
247
- z: 5,
248
- x: 27,
249
- y: 12,
250
- tileSize: 512,
251
- margin: 0,
252
- ext: 'png',
253
- quality: 90,
254
- cache,
255
- });
112
+ All options can be set via CLI flag or environment variable.
256
113
 
257
- const clipStream = await getRenderedClipStream({
258
- stylejson: 'file://localdata/style.json',
259
- bbox: [123.4, 34.5, 124.5, 35.6],
260
- size: 1024,
261
- ext: 'jpeg',
262
- quality: 85,
263
- cache,
264
- });
114
+ ### Server
265
115
 
266
- const cameraStream = await getRenderedCameraStream({
267
- stylejson: 'file://localdata/style.json',
268
- center: [139.69, 35.68],
269
- zoom: 10,
270
- bearing: 180,
271
- pitch: 60,
272
- width: 1024,
273
- height: 1024,
274
- ext: 'png',
275
- quality: 95,
276
- cache,
277
- })
278
- ```
116
+ | Flag | Env | Default |
117
+ | --- | --- | --- |
118
+ | `--port <n>` | `CHIITILER_PORT` | `3000` |
119
+ | `--debug` | `CHIITILER_DEBUG` | `false` |
120
+ | — | `CHIITILER_PROCESSES` | `1` (set `0` for all CPUs) |
121
+
122
+ ### Cache
123
+
124
+ | Flag | Env | Default |
125
+ | --- | --- | --- |
126
+ | `--cache <none\|memory\|file\|s3\|gcs>` | `CHIITILER_CACHE_METHOD` | `none` |
127
+ | `--cache-ttl <seconds>` | `CHIITILER_CACHE_TTL_SEC` | `3600` |
128
+ | `--memory-cache-max-item-count <n>` | `CHIITILER_MEMORYCACHE_MAXITEMCOUNT` | `1000` |
129
+ | `--file-cache-dir <dir>` | `CHIITILER_FILECACHE_DIR` | `./.cache` |
130
+ | `--s3-cache-bucket <name>` | `CHIITILER_S3CACHE_BUCKET` | — |
131
+ | `--s3-region <region>` | `CHIITILER_S3_REGION` | `us-east-1` |
132
+ | `--s3-endpoint <url>` | `CHIITILER_S3_ENDPOINT` | — |
133
+ | `--s3-force-path-style` | `CHIITILER_S3_FORCE_PATH_STYLE` | `false` |
134
+ | `--gcs-cache-bucket <name>` | `CHIITILER_GCS_CACHE_BUCKET` | — |
135
+ | `--gcs-project-id <id>` | `CHIITILER_GCS_PROJECT_ID` | — |
136
+ | `--gcs-key-filename <path>` | `CHIITILER_GCS_KEY_FILENAME` | — |
137
+ | `--gcs-cache-prefix <prefix>` | `CHIITILER_GCS_CACHE_PREFIX` | — |
138
+ | `--gcs-api-endpoint <url>` | `CHIITILER_GCS_API_ENDPOINT` | — |
139
+
140
+ Chiitiler caches *source assets* (vector tiles, glyphs, sprites) — not final rasters — so cached data is reused across requests. Standard AWS / GCP credentials (`AWS_ACCESS_KEY_ID`, `GOOGLE_APPLICATION_CREDENTIALS`, etc.) are respected.
279
141
 
280
142
  ## Deployment
281
143
 
282
- The [`cdk/`](./cdk) directory contains an AWS CDK app for running Chiitiler on Lambda with Web Adapter.
144
+ - **Docker** `ghcr.io/kanahiro/chiitiler:latest` (entrypoint: `tile-server`)
145
+ - **Docker Compose** — see [`docker-compose.yml`](./docker-compose.yml) (includes RustFS + fake-gcs-server for local testing)
146
+ - **AWS Lambda** — ready-to-deploy CDK app in [`cdk/`](./cdk)
147
+
148
+ ## Develop
149
+
150
+ Requires Node.js 24.12+ and `sharp` system deps (see [Dockerfile](./Dockerfile)).
151
+
152
+ ```bash
153
+ git clone https://github.com/Kanahiro/chiitiler.git
154
+ cd chiitiler
155
+ npm install
156
+ npm run dev # tsx watch mode
157
+ npm run test:unit # vitest
158
+ npm run test:integration # end-to-end
159
+ npm run test:benchmark # see BENCHMARK.md
160
+ npm run build # bundle to build/main.cjs
161
+ ```
283
162
 
284
163
  ## Architecture
285
164
 
@@ -288,10 +167,10 @@ graph LR
288
167
  subgraph sources
289
168
  direction LR
290
169
  A[style.json]
291
- z/x/y.pbf
292
- z/x/y.png/webp/jpg
293
- sprite
294
- glyphs
170
+ B[z/x/y.pbf]
171
+ C[z/x/y.png/webp/jpg]
172
+ D[sprite]
173
+ E[glyphs]
295
174
  end
296
175
 
297
176
  subgraph chiitiler
@@ -300,7 +179,14 @@ graph LR
300
179
  server
301
180
  end
302
181
 
303
- sources --> cache --> render --> server --/tiles/z/x/y--> png/webp/jpg
304
-
305
- cache <--get/set--> memory/file/s3/gcs
182
+ sources --> cache --> render --> server --/tiles/z/x/y--> png/webp/jpg
183
+ cache <--get/set--> memory/file/s3/gcs
306
184
  ```
185
+
186
+ ## Credits
187
+
188
+ Inspired by [`maptiler/tileserver-gl`](https://github.com/maptiler/tileserver-gl) and [`developmentseed/titiler`](https://github.com/developmentseed/titiler).
189
+
190
+ ## License
191
+
192
+ [MIT](./LICENSE) © Kanahiro Iguchi
@@ -73,9 +73,10 @@ function createCameraRouter(options) {
73
73
  })
74
74
  .post('/:zoom/:lat/:lon/:bearing/:pitch/:dimensions_ext', async (c) => {
75
75
  // body
76
- const { style } = await c.req.json();
77
- if (!isValidStylejson(style))
76
+ const body = await c.req.json().catch(() => null);
77
+ if (!isValidStylejson(body?.style))
78
78
  return c.body('invalid stylejson', 400);
79
+ const { style } = body;
79
80
  // path params
80
81
  const { zoom, lat, lon, bearing, pitch } = c.req.param();
81
82
  const [_dimensions, ext] = c.req.param('dimensions_ext').split('.');
@@ -42,9 +42,10 @@ function createClipRouter(options) {
42
42
  })
43
43
  .post('/:filename_ext', async (c) => {
44
44
  // body
45
- const { style } = await c.req.json();
46
- if (!isValidStylejson(style))
45
+ const body = await c.req.json().catch(() => null);
46
+ if (!isValidStylejson(body?.style))
47
47
  return c.body('invalid stylejson', 400);
48
+ const { style } = body;
48
49
  // path params
49
50
  const [filename, ext] = c.req.param('filename_ext').split('.');
50
51
  if (filename !== 'clip')
@@ -50,9 +50,10 @@ function createTilesRouter(options) {
50
50
  })
51
51
  .post('/:z/:x/:y_ext', async (c) => {
52
52
  // body
53
- const { style } = await c.req.json();
54
- if (!isValidStylejson(style))
53
+ const body = await c.req.json().catch(() => null);
54
+ if (!isValidStylejson(body?.style))
55
55
  return c.body('invalid stylejson', 400);
56
+ const { style } = body;
56
57
  // path params
57
58
  const z = Number(c.req.param('z'));
58
59
  const x = Number(c.req.param('x'));
@@ -1,5 +1,7 @@
1
1
  import { validateStyleMin, } from '@maplibre/maplibre-gl-style-spec';
2
2
  function isValidStylejson(stylejson) {
3
+ if (stylejson === null || typeof stylejson !== 'object')
4
+ return false;
3
5
  return validateStyleMin(stylejson).length === 0;
4
6
  }
5
7
  function isSupportedFormat(ext) {
package/package.json CHANGED
@@ -1,56 +1,58 @@
1
1
  {
2
- "type": "module",
3
- "name": "chiitiler",
4
- "version": "1.20.1",
5
- "description": "Tiny map rendering server for MapLibre Style Spec",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "files": [
9
- "dist"
10
- ],
11
- "scripts": {
12
- "build": "npx esbuild --bundle src/main.ts --minify --outfile=build/main.cjs --platform=node --external:@maplibre/maplibre-gl-native --external:sharp",
13
- "check": "tsc --noEmit",
14
- "dev": "tsx watch src/main.ts tile-server -D",
15
- "test:unit": "vitest src",
16
- "test:coverage": "vitest src --coverage --coverage.provider=v8",
17
- "test:integration": "vitest tests/integration.test.ts",
18
- "test:benchmark": "vitest bench"
19
- },
20
- "keywords": [],
21
- "author": "Kanahiro Iguchi",
22
- "license": "MIT",
23
- "repository": {
24
- "url": "https://github.com/Kanahiro/chiitiler"
25
- },
26
- "devDependencies": {
27
- "@tsconfig/node24": "^24.0.4",
28
- "@types/better-sqlite3": "^7.6.13",
29
- "@types/node": "^25.6.0",
30
- "@vitest/coverage-v8": "^4.1.4",
31
- "esbuild": "^0.28.0",
32
- "image-size": "^2.0.2",
33
- "tsx": "^4.21.0",
34
- "typescript": "^6.0.3",
35
- "vitest": "^4.1.4"
36
- },
37
- "dependencies": {
38
- "@aws-sdk/client-s3": "^3.1032.0",
39
- "@google-cloud/storage": "^7.19.0",
40
- "@hono/node-server": "^2.0.0",
41
- "@mapbox/sphericalmercator": "^2.0.2",
42
- "@mapbox/tilebelt": "^2.0.3",
43
- "@maplibre/maplibre-gl-native": "^6.4.1",
44
- "@maplibre/maplibre-gl-style-spec": "^24.8.1",
45
- "better-sqlite3": "12.9.0",
46
- "commander": "^14.0.3",
47
- "file-system-cache": "^2.4.7",
48
- "higuruma": "^0.1.6",
49
- "hono": "^4.12.14",
50
- "lightning-pool": "^4.12.0",
51
- "lru-cache": "^11.3.5",
52
- "maplibre-gl": "^5.23.0",
53
- "pmtiles": "^4.4.1",
54
- "sharp": "^0.34.5"
55
- }
2
+ "type": "module",
3
+ "name": "chiitiler",
4
+ "version": "1.20.3",
5
+ "description": "Tiny map rendering server for MapLibre Style Spec",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "npx esbuild --bundle src/main.ts --minify --outfile=build/main.cjs --platform=node --external:@maplibre/maplibre-gl-native --external:sharp",
13
+ "check": "tsc --noEmit",
14
+ "dev": "tsx watch src/main.ts tile-server -D",
15
+ "test:unit": "vitest src",
16
+ "test:coverage": "vitest src --coverage --coverage.provider=v8",
17
+ "test:integration": "vitest tests/integration.test.ts",
18
+ "test:benchmark": "tsx tests/benchmark.ts"
19
+ },
20
+ "keywords": [],
21
+ "author": "Kanahiro Iguchi",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "url": "https://github.com/Kanahiro/chiitiler"
25
+ },
26
+ "devDependencies": {
27
+ "@tsconfig/node24": "^24.0.4",
28
+ "@types/autocannon": "^7.12.7",
29
+ "@types/better-sqlite3": "^7.6.13",
30
+ "@types/node": "^25.6.0",
31
+ "@vitest/coverage-v8": "^4.1.4",
32
+ "autocannon": "^8.0.0",
33
+ "esbuild": "^0.28.0",
34
+ "image-size": "^2.0.2",
35
+ "tsx": "^4.21.0",
36
+ "typescript": "^6.0.3",
37
+ "vitest": "^4.1.4"
38
+ },
39
+ "dependencies": {
40
+ "@aws-sdk/client-s3": "^3.1032.0",
41
+ "@google-cloud/storage": "^7.19.0",
42
+ "@hono/node-server": "^2.0.0",
43
+ "@mapbox/sphericalmercator": "^2.0.2",
44
+ "@mapbox/tilebelt": "^2.0.3",
45
+ "@maplibre/maplibre-gl-native": "^6.4.1",
46
+ "@maplibre/maplibre-gl-style-spec": "^24.8.1",
47
+ "better-sqlite3": "12.9.0",
48
+ "commander": "^14.0.3",
49
+ "file-system-cache": "^2.4.7",
50
+ "higuruma": "^0.1.6",
51
+ "hono": "^4.12.14",
52
+ "lightning-pool": "^4.12.0",
53
+ "lru-cache": "^11.3.5",
54
+ "maplibre-gl": "^5.23.0",
55
+ "pmtiles": "^4.4.1",
56
+ "sharp": "^0.34.5"
57
+ }
56
58
  }