styled-map-package-api 5.0.0-pre.3 → 5.0.0-pre.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.
Files changed (94) hide show
  1. package/README.md +94 -0
  2. package/dist/download.d.ts +11 -21
  3. package/dist/fallbacks.d.ts +32 -0
  4. package/dist/from-mbtiles.d.ts +1 -3
  5. package/dist/index.d.ts +11 -24
  6. package/dist/reader.d.ts +28 -12
  7. package/dist/server.d.ts +23 -14
  8. package/dist/style-downloader.d.ts +13 -19
  9. package/dist/tile-downloader.d.ts +13 -23
  10. package/dist/types.d.ts +61 -0
  11. package/dist/utils/errors.d.ts +2 -4
  12. package/dist/utils/fetch.d.ts +3 -8
  13. package/dist/utils/file-formats.d.ts +3 -10
  14. package/dist/utils/geo.d.ts +17 -9
  15. package/dist/utils/mapbox.d.ts +8 -10
  16. package/dist/utils/misc.d.ts +3 -5
  17. package/dist/utils/streams.d.ts +6 -10
  18. package/dist/utils/style.d.ts +27 -16
  19. package/dist/utils/templates.d.ts +30 -25
  20. package/dist/validator.d.ts +66 -0
  21. package/dist/writer.d.ts +157 -4
  22. package/lib/download.js +125 -0
  23. package/lib/fallbacks.js +157 -0
  24. package/lib/from-mbtiles.js +131 -0
  25. package/lib/index.js +12 -0
  26. package/lib/reader.js +360 -0
  27. package/lib/server.js +222 -0
  28. package/lib/style-downloader.js +369 -0
  29. package/lib/tile-downloader.js +189 -0
  30. package/lib/types.ts +99 -0
  31. package/lib/utils/errors.js +24 -0
  32. package/lib/utils/fetch.js +104 -0
  33. package/lib/utils/file-formats.js +92 -0
  34. package/lib/utils/geo.js +97 -0
  35. package/lib/utils/mapbox.js +155 -0
  36. package/{dist/utils/misc.d.cts → lib/utils/misc.js} +9 -5
  37. package/lib/utils/streams.js +101 -0
  38. package/lib/utils/style.js +206 -0
  39. package/lib/utils/templates.js +165 -0
  40. package/lib/validator.js +789 -0
  41. package/lib/writer.js +652 -0
  42. package/package.json +30 -78
  43. package/dist/download.cjs +0 -100
  44. package/dist/download.d.cts +0 -63
  45. package/dist/download.js +0 -76
  46. package/dist/from-mbtiles.cjs +0 -127
  47. package/dist/from-mbtiles.d.cts +0 -14
  48. package/dist/from-mbtiles.js +0 -103
  49. package/dist/index.cjs +0 -46
  50. package/dist/index.d.cts +0 -24
  51. package/dist/index.js +0 -16
  52. package/dist/reader.cjs +0 -287
  53. package/dist/reader.d.cts +0 -67
  54. package/dist/reader.js +0 -259
  55. package/dist/server.cjs +0 -73
  56. package/dist/server.d.cts +0 -45
  57. package/dist/server.js +0 -49
  58. package/dist/style-downloader.cjs +0 -314
  59. package/dist/style-downloader.d.cts +0 -118
  60. package/dist/style-downloader.js +0 -290
  61. package/dist/tile-downloader.cjs +0 -156
  62. package/dist/tile-downloader.d.cts +0 -82
  63. package/dist/tile-downloader.js +0 -124
  64. package/dist/types-Bhn0-Ldk.d.cts +0 -201
  65. package/dist/types-Bhn0-Ldk.d.ts +0 -201
  66. package/dist/utils/errors.cjs +0 -41
  67. package/dist/utils/errors.d.cts +0 -18
  68. package/dist/utils/errors.js +0 -16
  69. package/dist/utils/fetch.cjs +0 -97
  70. package/dist/utils/fetch.d.cts +0 -50
  71. package/dist/utils/fetch.js +0 -63
  72. package/dist/utils/file-formats.cjs +0 -96
  73. package/dist/utils/file-formats.d.cts +0 -32
  74. package/dist/utils/file-formats.js +0 -70
  75. package/dist/utils/geo.cjs +0 -84
  76. package/dist/utils/geo.d.cts +0 -46
  77. package/dist/utils/geo.js +0 -56
  78. package/dist/utils/mapbox.cjs +0 -121
  79. package/dist/utils/mapbox.d.cts +0 -43
  80. package/dist/utils/mapbox.js +0 -91
  81. package/dist/utils/misc.cjs +0 -39
  82. package/dist/utils/misc.js +0 -13
  83. package/dist/utils/streams.cjs +0 -99
  84. package/dist/utils/streams.d.cts +0 -49
  85. package/dist/utils/streams.js +0 -73
  86. package/dist/utils/style.cjs +0 -126
  87. package/dist/utils/style.d.cts +0 -66
  88. package/dist/utils/style.js +0 -98
  89. package/dist/utils/templates.cjs +0 -124
  90. package/dist/utils/templates.d.cts +0 -79
  91. package/dist/utils/templates.js +0 -85
  92. package/dist/writer.cjs +0 -539
  93. package/dist/writer.d.cts +0 -4
  94. package/dist/writer.js +0 -516
package/README.md CHANGED
@@ -43,6 +43,53 @@ const server = createServer()
43
43
  // server.fetch(request, reader) returns a WHATWG Response
44
44
  ```
45
45
 
46
+ ### Fallback tiles and glyphs
47
+
48
+ When an SMP file doesn't contain every tile or glyph range that the style references, `createServer` can call fallback handlers instead of returning a 404. This is useful for previewing incomplete packages or packages that only cover a partial area/zoom range.
49
+
50
+ Built-in fallback handlers are provided:
51
+
52
+ ```js
53
+ import {
54
+ emptyTileFallback,
55
+ emptyGlyphFallback,
56
+ } from 'styled-map-package-api/fallbacks'
57
+ import { createServer } from 'styled-map-package-api/server'
58
+
59
+ const server = createServer({
60
+ fallbackTile: emptyTileFallback,
61
+ fallbackGlyph: emptyGlyphFallback,
62
+ })
63
+ ```
64
+
65
+ - **`emptyTileFallback(tileId, sourceInfo)`** — Returns an appropriate empty tile based on the source's tile format: empty gzipped MVT for vector sources, 1×1 transparent PNG/WebP for raster sources.
66
+ - **`emptyGlyphFallback(fontstack, range)`** — Returns an empty gzipped PBF (valid protobuf with no glyph entries), causing MapLibre to render missing characters as blank space instead of erroring on a 404.
67
+
68
+ For real glyph rendering with Noto Sans (80+ scripts), use the [`smp-noto-glyphs`](../glyphs/) package:
69
+
70
+ ```js
71
+ import { notoGlyphFallback } from 'smp-noto-glyphs'
72
+
73
+ const server = createServer({
74
+ fallbackTile: emptyTileFallback,
75
+ fallbackGlyph: notoGlyphFallback,
76
+ })
77
+ ```
78
+
79
+ You can also provide custom fallback handlers, for example to proxy missing tiles from an online source:
80
+
81
+ ```js
82
+ const server = createServer({
83
+ fallbackTile: async (tileId, { sourceId, source }) => {
84
+ const url = `https://tiles.example.com/${tileId.z}/${tileId.x}/${tileId.y}.mvt`
85
+ return fetch(url)
86
+ },
87
+ fallbackGlyph: async (fontstack, range) => {
88
+ return fetch(`https://fonts.example.com/${fontstack}/${range}.pbf`)
89
+ },
90
+ })
91
+ ```
92
+
46
93
  ### Downloading a map for offline use
47
94
 
48
95
  ```js
@@ -52,10 +99,13 @@ const stream = download({
52
99
  styleUrl: 'https://demotiles.maplibre.org/style.json',
53
100
  bbox: [-180, -80, 180, 80],
54
101
  maxzoom: 5,
102
+ skipLocalGlyphs: true, // skip CJK/Hangul/Kana ranges rendered locally by MapLibre
55
103
  })
56
104
  // Pipe the ReadableStream to a file
57
105
  ```
58
106
 
107
+ The `skipLocalGlyphs` option skips downloading glyph ranges that MapLibre GL renders client-side via [`localIdeographFontFamily`](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/) (CJK, Hangul, Kana, Yi, and Halfwidth/Fullwidth Forms — 163 of 256 ranges). This significantly reduces download size for styles that use these scripts.
108
+
59
109
  ### Converting from MBTiles
60
110
 
61
111
  > **Note:** MBTiles conversion requires Node >= 20 (uses `better-sqlite3` which dropped Node 18 support).
@@ -82,12 +132,56 @@ const stream = fromMBTiles(buffer)
82
132
  | `styled-map-package-api/reader` | `Reader` class for reading `.smp` files |
83
133
  | `styled-map-package-api/writer` | `Writer` class for creating `.smp` files |
84
134
  | `styled-map-package-api/server` | `createServer()` — HTTP handler using WHATWG Request/Response |
135
+ | `styled-map-package-api/fallbacks` | `emptyTileFallback`, `emptyGlyphFallback` — built-in fallbacks |
85
136
  | `styled-map-package-api/download` | `download()` — download an online map style for offline use |
86
137
  | `styled-map-package-api/style-downloader` | `StyleDownloader` — downloads styles, sprites, and glyphs |
87
138
  | `styled-map-package-api/tile-downloader` | `downloadTiles()` — downloads tile data |
88
139
  | `styled-map-package-api/from-mbtiles` | `fromMBTiles()` — convert MBTiles to SMP stream |
140
+ | `styled-map-package-api/validator` | `validate()` — validate `.smp` files against the spec |
89
141
  | `styled-map-package-api/utils/mapbox` | Mapbox URL detection and API utilities |
90
142
 
143
+ ### Validating an SMP file
144
+
145
+ ```js
146
+ import { validate } from 'styled-map-package-api/validator'
147
+
148
+ const result = await validate('path/to/map.smp')
149
+
150
+ if (!result.usable) {
151
+ console.error('File cannot be opened')
152
+ } else if (!result.valid) {
153
+ console.warn('File has issues but is usable')
154
+ }
155
+
156
+ for (const issue of result.issues) {
157
+ console.log(`[${issue.severity}] ${issue.message}`)
158
+ }
159
+ ```
160
+
161
+ The validator checks an `.smp` file against the [SMP specification](../../spec/1.0/) and returns structured issues. Each issue has:
162
+
163
+ - **`kind`** — `'error'` (spec MUST violation) or `'warning'` (SHOULD/RECOMMENDED)
164
+ - **`severity`** — practical impact on the reader/renderer:
165
+ - `'fatal'` — the reader will fail to open the file
166
+ - `'rendering'` — the map opens but content will be visibly broken (missing tiles, glyphs, sprites)
167
+ - `'spec'` — non-compliance that doesn't affect practical use
168
+ - **`type`** — stable identifier for programmatic filtering (e.g. `'missing_tiles'`, `'incomplete_font_glyphs'`)
169
+ - **`message`** — human-readable description
170
+ - **`path`** — location context (e.g. `'sources.test.tiles'`, `'glyphs'`)
171
+
172
+ The result includes two convenience booleans:
173
+
174
+ - **`valid`** — `true` when there are no errors (spec-compliant)
175
+ - **`usable`** — `true` when there are no fatal issues (the file can be opened)
176
+
177
+ Accepts a file path (Node.js) or a `ZipReader` instance (browser). Options:
178
+
179
+ ```js
180
+ const result = await validate('map.smp', {
181
+ maxEntries: 500_000, // max ZIP entries before aborting (default: 500,000)
182
+ })
183
+ ```
184
+
91
185
  ### Browser support
92
186
 
93
187
  All stream APIs use WHATWG `ReadableStream`, making the library compatible with both Node.js and browser environments. The `Reader` class accepts either a file path (Node.js) or a `ZipReader` instance (browser).
@@ -1,15 +1,3 @@
1
- import { GlyphDownloadStats } from './style-downloader.js';
2
- import { TileDownloadStats } from './tile-downloader.js';
3
- import { D as DownloadStream } from './types-Bhn0-Ldk.js';
4
- import { BBox } from './utils/geo.js';
5
- import 'ky';
6
- import '@maplibre/maplibre-gl-style-spec';
7
- import './utils/fetch.js';
8
- import './utils/streams.js';
9
- import 'stream/web';
10
- import 'geojson';
11
- import 'type-fest';
12
-
13
1
  /**
14
2
  * @typedef {object} DownloadProgress
15
3
  * @property {import('./tile-downloader.js').TileDownloadStats & { done: boolean }} tiles
@@ -25,22 +13,26 @@ import 'type-fest';
25
13
  * containing all the resources needed to serve the style offline.
26
14
  *
27
15
  * @param {object} opts
28
- * @param {import("./utils/geo.js").BBox} opts.bbox Bounding box to download tiles for
16
+ * @param {Readonly<import("./utils/geo.js").BBox>} opts.bbox Bounding box to download tiles for
29
17
  * @param {number} opts.maxzoom Max zoom level to download tiles for
30
18
  * @param {string} opts.styleUrl URL of the style to download
31
19
  * @param { (progress: DownloadProgress) => void } [opts.onprogress] Optional callback for reporting progress
32
20
  * @param {string} [opts.accessToken]
21
+ * @param {boolean} [opts.skipLocalGlyphs] Skip glyph ranges rendered client-side by MapLibre GL via localIdeographFontFamily (CJK, Hangul, Kana, Yi, etc.)
22
+ * @param {boolean} [opts.dedupe] When true, duplicate tiles are stored only once (see {@link Writer})
33
23
  * @returns {import('./types.js').DownloadStream} Readable stream of the output styled map file
34
24
  */
35
- declare function download({ bbox, maxzoom, styleUrl, onprogress, accessToken }: {
36
- bbox: BBox;
25
+ export function download({ bbox, maxzoom, styleUrl, onprogress, accessToken, skipLocalGlyphs, dedupe, }: {
26
+ bbox: Readonly<import("./utils/geo.js").BBox>;
37
27
  maxzoom: number;
38
28
  styleUrl: string;
39
29
  onprogress?: ((progress: DownloadProgress) => void) | undefined;
40
30
  accessToken?: string | undefined;
41
- }): DownloadStream;
42
- type DownloadProgress = {
43
- tiles: TileDownloadStats & {
31
+ skipLocalGlyphs?: boolean | undefined;
32
+ dedupe?: boolean | undefined;
33
+ }): import("./types.js").DownloadStream;
34
+ export type DownloadProgress = {
35
+ tiles: import("./tile-downloader.js").TileDownloadStats & {
44
36
  done: boolean;
45
37
  };
46
38
  style: {
@@ -50,7 +42,7 @@ type DownloadProgress = {
50
42
  downloaded: number;
51
43
  done: boolean;
52
44
  };
53
- glyphs: GlyphDownloadStats & {
45
+ glyphs: import("./style-downloader.js").GlyphDownloadStats & {
54
46
  done: boolean;
55
47
  };
56
48
  output: {
@@ -59,5 +51,3 @@ type DownloadProgress = {
59
51
  };
60
52
  elapsedMs: number;
61
53
  };
62
-
63
- export { type DownloadProgress, download };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Fallback tile handler for use with `createServer({ fallbackTile })`.
3
+ * Returns an appropriate empty tile based on the source's tile format:
4
+ * - vector sources → empty gzipped MVT
5
+ * - raster PNG sources → 1×1 transparent PNG
6
+ * - raster WebP sources → 1×1 transparent WebP
7
+ * - raster JPEG sources → 1×1 transparent PNG (no such thing as transparent JPEG)
8
+ *
9
+ * @param {{ x: number, y: number, z: number }} _tileId
10
+ * @param {{ sourceId: string, source: SMPSource }} sourceInfo
11
+ * @returns {Response}
12
+ */
13
+ export function emptyTileFallback(_tileId: {
14
+ x: number;
15
+ y: number;
16
+ z: number;
17
+ }, { source }: {
18
+ sourceId: string;
19
+ source: SMPSource;
20
+ }): Response;
21
+ /**
22
+ * Fallback glyph handler for use with `createServer({ fallbackGlyph })`.
23
+ * Returns an empty gzipped PBF (valid protobuf with no glyph entries), which
24
+ * causes MapLibre to render missing characters as blank space instead of
25
+ * erroring on a 404.
26
+ *
27
+ * @param {string} _fontstack
28
+ * @param {string} _range
29
+ * @returns {Response}
30
+ */
31
+ export function emptyGlyphFallback(_fontstack: string, _range: string): Response;
32
+ import type { SMPSource } from './types.js';
@@ -9,6 +9,4 @@
9
9
  * (Node), OPFS path (browser Worker), or in-memory buffer.
10
10
  * @returns {ReadableStream<Uint8Array>}
11
11
  */
12
- declare function fromMBTiles(source: string | ArrayBuffer | Uint8Array): ReadableStream<Uint8Array>;
13
-
14
- export { fromMBTiles };
12
+ export function fromMBTiles(source: string | ArrayBuffer | Uint8Array): ReadableStream<Uint8Array>;
package/dist/index.d.ts CHANGED
@@ -1,24 +1,11 @@
1
- import { S as SMPSource$1, a as SMPStyle$1 } from './types-Bhn0-Ldk.js';
2
- export { W as Writer } from './types-Bhn0-Ldk.js';
3
- export { Reader } from './reader.js';
4
- export { createServer } from './server.js';
5
- export { StyleDownloader } from './style-downloader.js';
6
- export { downloadTiles } from './tile-downloader.js';
7
- export { download } from './download.js';
8
- export { fromMBTiles } from './from-mbtiles.js';
9
- import '@maplibre/maplibre-gl-style-spec';
10
- import 'geojson';
11
- import 'type-fest';
12
- import '@gmaclennan/zip-reader';
13
- import 'itty-router';
14
- import 'itty-router/IttyRouter';
15
- import 'ky';
16
- import './utils/geo.js';
17
- import './utils/fetch.js';
18
- import './utils/streams.js';
19
- import 'stream/web';
20
-
21
- type SMPSource = SMPSource$1;
22
- type SMPStyle = SMPStyle$1;
23
-
24
- export type { SMPSource, SMPStyle };
1
+ export { Reader } from "./reader.js";
2
+ export { Writer } from "./writer.js";
3
+ export { createServer } from "./server.js";
4
+ export { StyleDownloader } from "./style-downloader.js";
5
+ export { downloadTiles } from "./tile-downloader.js";
6
+ export { download } from "./download.js";
7
+ export { fromMBTiles } from "./from-mbtiles.js";
8
+ export { validate } from "./validator.js";
9
+ export type SMPSource = import("./types.js").SMPSource;
10
+ export type SMPStyle = import("./types.js").SMPStyle;
11
+ export { emptyTileFallback, emptyGlyphFallback } from "./fallbacks.js";
package/dist/reader.d.ts CHANGED
@@ -1,9 +1,3 @@
1
- import { a as SMPStyle } from './types-Bhn0-Ldk.js';
2
- import * as _gmaclennan_zip_reader from '@gmaclennan/zip-reader';
3
- import '@maplibre/maplibre-gl-style-spec';
4
- import 'geojson';
5
- import 'type-fest';
6
-
7
1
  /**
8
2
  * @typedef {object} Resource
9
3
  * @property {string} resourceType
@@ -12,15 +6,25 @@ import 'type-fest';
12
6
  * @property {ReadableStream<Uint8Array>} stream
13
7
  * @property {'gzip'} [contentEncoding]
14
8
  */
9
+ /**
10
+ * @typedef {object} ReaderOptions
11
+ * @property {number} [maxEntries=500_000] Maximum number of ZIP entries to
12
+ * process. Exceeding this limit throws an error during `opened()`. Default is
13
+ * 500,000 (~a global z9 tileset).
14
+ * @property {number} [maxResourceSize=20 * 1024 * 1024] Maximum uncompressed
15
+ * size in bytes for a single resource returned by `getResource()`. Default is
16
+ * 20 MiB.
17
+ */
15
18
  /**
16
19
  * A low-level reader for styled map packages. Returns resources in the package
17
20
  * as readable streams, for serving over HTTP for example.
18
21
  */
19
- declare class Reader {
22
+ export class Reader {
20
23
  /**
21
24
  * @param {string | import('@gmaclennan/zip-reader').ZipReader} filepathOrZip Path to styled map package (`.styledmap`) file, or a ZipReader instance
25
+ * @param {ReaderOptions} [options]
22
26
  */
23
- constructor(filepathOrZip: string | _gmaclennan_zip_reader.ZipReader);
27
+ constructor(filepathOrZip: string | import("@gmaclennan/zip-reader").ZipReader, options?: ReaderOptions);
24
28
  /**
25
29
  * Resolves when the styled map package has been opened and the entries have
26
30
  * been read. Throws any error that occurred during opening.
@@ -41,7 +45,7 @@ declare class Reader {
41
45
  * @param {string | null} [baseUrl] Base URL where you plan to serve the resources in this styled map package, e.g. `http://localhost:3000/maps/styleA`
42
46
  * @returns {Promise<import('./types.js').SMPStyle>}
43
47
  */
44
- getStyle(baseUrl?: string | null): Promise<SMPStyle>;
48
+ getStyle(baseUrl?: string | null): Promise<import("./types.js").SMPStyle>;
45
49
  /**
46
50
  * Get a resource from the styled map package. The path should be relative to
47
51
  * the root of the package.
@@ -56,12 +60,24 @@ declare class Reader {
56
60
  close(): Promise<void>;
57
61
  #private;
58
62
  }
59
- type Resource = {
63
+ export type Resource = {
60
64
  resourceType: string;
61
65
  contentType: string;
62
66
  contentLength: number;
63
67
  stream: ReadableStream<Uint8Array>;
64
68
  contentEncoding?: "gzip" | undefined;
65
69
  };
66
-
67
- export { Reader, type Resource };
70
+ export type ReaderOptions = {
71
+ /**
72
+ * Maximum number of ZIP entries to
73
+ * process. Exceeding this limit throws an error during `opened()`. Default is
74
+ * 500,000 (~a global z9 tileset).
75
+ */
76
+ maxEntries?: number | undefined;
77
+ /**
78
+ * Maximum uncompressed
79
+ * size in bytes for a single resource returned by `getResource()`. Default is
80
+ * 20 MiB.
81
+ */
82
+ maxResourceSize?: number | undefined;
83
+ };
package/dist/server.d.ts CHANGED
@@ -1,12 +1,3 @@
1
- import { RequestLike } from 'itty-router';
2
- import { Reader } from './reader.js';
3
- import { IttyRouter } from 'itty-router/IttyRouter';
4
- import './types-Bhn0-Ldk.js';
5
- import '@maplibre/maplibre-gl-style-spec';
6
- import 'geojson';
7
- import 'type-fest';
8
- import '@gmaclennan/zip-reader';
9
-
10
1
  /**
11
2
  * Create a server for serving styled map packages (SMP) over http. The server
12
3
  * is a `fetch` handler that must be provided a WHATWG `Request` and a SMP
@@ -32,14 +23,32 @@ import '@gmaclennan/zip-reader';
32
23
  *
33
24
  * @param {object} [options]
34
25
  * @param {string} [options.base='/'] Base path for the server routes
26
+ * @param {(tileId: { x: number, y: number, z: number }, sourceInfo: { sourceId: string, source: import('./types.js').SMPSource }) => Response | Promise<Response>} [options.fallbackTile] Called when a tile is missing from the SMP
27
+ * @param {(fontstack: string, range: string) => Response | Promise<Response>} [options.fallbackGlyph] Called when a glyph is missing from the SMP
35
28
  * @returns {{ fetch: (request: RequestLike, reader: ReaderLike) => Promise<Response> }} server instance
36
29
  */
37
- declare function createServer({ base }?: {
30
+ export function createServer({ base, fallbackTile, fallbackGlyph }?: {
38
31
  base?: string | undefined;
32
+ fallbackTile?: ((tileId: {
33
+ x: number;
34
+ y: number;
35
+ z: number;
36
+ }, sourceInfo: {
37
+ sourceId: string;
38
+ source: import("./types.js").SMPSource;
39
+ }) => Response | Promise<Response>) | undefined;
40
+ fallbackGlyph?: ((fontstack: string, range: string) => Response | Promise<Response>) | undefined;
39
41
  }): {
40
42
  fetch: (request: RequestLike, reader: ReaderLike) => Promise<Response>;
41
43
  };
42
- type ReaderLike = Pick<Reader, keyof Reader>;
43
- type RouterType = typeof IttyRouter<IRequestStrict, [ReaderLike], Response>;
44
-
45
- export { type ReaderLike, type RouterType, createServer };
44
+ export type ReaderLike = Pick<Reader, keyof Reader>;
45
+ export type RouterType = typeof IttyRouter<IRequestStrict, [ReaderLike], Response>;
46
+ export type TileMatcher = {
47
+ regex: RegExp;
48
+ sourceId: string;
49
+ source: import("./types.js").SMPSource;
50
+ };
51
+ import type { RequestLike } from 'itty-router';
52
+ import type { Reader } from './reader.js';
53
+ import { IttyRouter } from 'itty-router/IttyRouter';
54
+ import type { IRequestStrict } from 'itty-router';
@@ -1,14 +1,3 @@
1
- import * as ky from 'ky';
2
- import { BBox } from './utils/geo.js';
3
- import { b as StyleInlinedSources, G as GlyphInfo, T as TileInfo } from './types-Bhn0-Ldk.js';
4
- import { TileDownloadStats } from './tile-downloader.js';
5
- import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
6
- import 'geojson';
7
- import 'type-fest';
8
- import './utils/fetch.js';
9
- import './utils/streams.js';
10
- import 'stream/web';
11
-
12
1
  /** @import { SourceSpecification, StyleSpecification } from '@maplibre/maplibre-gl-style-spec' */
13
2
  /** @import { TileInfo, GlyphInfo, GlyphRange } from './writer.js' */
14
3
  /** @import { TileDownloadStats } from './tile-downloader.js' */
@@ -25,7 +14,7 @@ import 'stream/web';
25
14
  * Download a style and its resources for offline use. Please check the terms of
26
15
  * service of the map provider you are using before downloading any resources.
27
16
  */
28
- declare class StyleDownloader {
17
+ export class StyleDownloader {
29
18
  /**
30
19
  * @param {string | StyleSpecification} style A url to a style JSON file or a style object
31
20
  * @param {object} [opts]
@@ -71,10 +60,12 @@ declare class StyleDownloader {
71
60
  *
72
61
  * @param {object} opts
73
62
  * @param {(progress: GlyphDownloadStats) => void} [opts.onprogress]
63
+ * @param {boolean} [opts.skipLocalGlyphs] Skip glyph ranges rendered client-side by MapLibre GL via localIdeographFontFamily (CJK, Hangul, Kana, Yi, etc.)
74
64
  * @returns {AsyncGenerator<[ReadableStream<Uint8Array>, GlyphInfo]>}
75
65
  */
76
- getGlyphs({ onprogress }?: {
66
+ getGlyphs({ onprogress, skipLocalGlyphs }?: {
77
67
  onprogress?: ((progress: GlyphDownloadStats) => void) | undefined;
68
+ skipLocalGlyphs?: boolean | undefined;
78
69
  }): AsyncGenerator<[ReadableStream<Uint8Array>, GlyphInfo]>;
79
70
  /**
80
71
  * Get all the tiles for this style within the given bounds and zoom range.
@@ -87,14 +78,14 @@ declare class StyleDownloader {
87
78
  * bytes downloaded.
88
79
  *
89
80
  * @param {object} opts
90
- * @param {import('./utils/geo.js').BBox} opts.bounds
81
+ * @param {Readonly<import('./utils/geo.js').BBox>} opts.bounds
91
82
  * @param {number} opts.maxzoom
92
83
  * @param {(progress: TileDownloadStats) => void} [opts.onprogress]
93
84
  * @param {boolean} [opts.trackErrors=false] Include errors in the returned array of skipped tiles - this has memory overhead so should only be used for debugging.
94
85
  * @returns {AsyncGenerator<[ReadableStream<Uint8Array>, TileInfo]> & { readonly skipped: Array<TileInfo & { error?: Error }>, readonly stats: TileDownloadStats }}
95
86
  */
96
87
  getTiles({ bounds, maxzoom, onprogress, trackErrors }: {
97
- bounds: BBox;
88
+ bounds: Readonly<import("./utils/geo.js").BBox>;
98
89
  maxzoom: number;
99
90
  onprogress?: ((progress: TileDownloadStats) => void) | undefined;
100
91
  trackErrors?: boolean | undefined;
@@ -106,13 +97,16 @@ declare class StyleDownloader {
106
97
  };
107
98
  #private;
108
99
  }
109
- type ResponsePromise = ky.ResponsePromise & {
100
+ export type ResponsePromise = import("ky").ResponsePromise & {
110
101
  body: ReadableStream<Uint8Array>;
111
102
  };
112
- type GlyphDownloadStats = {
103
+ export type GlyphDownloadStats = {
113
104
  total: number;
114
105
  downloaded: number;
115
106
  totalBytes: number;
116
107
  };
117
-
118
- export { type GlyphDownloadStats, type ResponsePromise, StyleDownloader };
108
+ import type { StyleInlinedSources } from './types.js';
109
+ import type { GlyphInfo } from './writer.js';
110
+ import type { TileDownloadStats } from './tile-downloader.js';
111
+ import type { TileInfo } from './writer.js';
112
+ import type { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
@@ -1,12 +1,3 @@
1
- import { T as TileInfo$1 } from './types-Bhn0-Ldk.js';
2
- import { BBox } from './utils/geo.js';
3
- import { FetchQueue } from './utils/fetch.js';
4
- import '@maplibre/maplibre-gl-style-spec';
5
- import 'geojson';
6
- import 'type-fest';
7
- import './utils/streams.js';
8
- import 'stream/web';
9
-
10
1
  /** @typedef {Omit<import('./writer.js').TileInfo, 'sourceId'>} TileInfo */
11
2
  /**
12
3
  * @typedef {object} TileDownloadStats
@@ -21,11 +12,11 @@ import 'stream/web';
21
12
  *
22
13
  * @param {object} opts
23
14
  * @param {string[]} opts.tileUrls Array of tile URL templates. Use `{x}`, `{y}`, `{z}` placeholders, and optional `{scheme}` placeholder which can be `xyz` or `tms`.
24
- * @param {import('./utils/geo.js').BBox} opts.bounds Bounding box of the area to download
15
+ * @param {Readonly<import('./utils/geo.js').BBox>} opts.bounds Bounding box of the area to download
25
16
  * @param {number} opts.maxzoom Maximum zoom level to download
26
17
  * @param {(progress: TileDownloadStats) => void} [opts.onprogress] Callback to report download progress
27
18
  * @param {boolean} [opts.trackErrors=false] Include errors in the returned array of skipped tiles - this has memory overhead so should only be used for debugging.
28
- * @param {import('./utils/geo.js').BBox} [opts.sourceBounds=MAX_BOUNDS] Bounding box of source data.
19
+ * @param {Readonly<import('./utils/geo.js').BBox>} [opts.sourceBounds=MAX_BOUNDS] Bounding box of source data.
29
20
  * @param {boolean} [opts.boundsBuffer=false] Buffer the bounds by one tile at each zoom level to ensure no tiles are missed at the edges. With this set to false, in most instances the map will appear incomplete when viewed because the downloaded tiles at lower zoom levels will not cover the map view area.
30
21
  * @param {number} [opts.minzoom=0] Minimum zoom level to download (for most cases this should be left as `0` - the size overhead is minimal, because each zoom level has 4x as many tiles)
31
22
  * @param {number} [opts.concurrency=8] Number of concurrent downloads (ignored if `fetchQueue` is provided)
@@ -33,13 +24,13 @@ import 'stream/web';
33
24
  * @param {'xyz' | 'tms'} [opts.scheme='xyz'] Tile scheme to use for tile URLs
34
25
  * @returns {AsyncGenerator<[ReadableStream<Uint8Array>, TileInfo]> & { readonly skipped: Array<TileInfo & { error?: Error }>, readonly stats: TileDownloadStats }}
35
26
  */
36
- declare function downloadTiles({ tileUrls, bounds, maxzoom, onprogress, trackErrors, sourceBounds, boundsBuffer, minzoom, concurrency, fetchQueue, scheme, }: {
27
+ export function downloadTiles({ tileUrls, bounds, maxzoom, onprogress, trackErrors, sourceBounds, boundsBuffer, minzoom, concurrency, fetchQueue, scheme, }: {
37
28
  tileUrls: string[];
38
- bounds: BBox;
29
+ bounds: Readonly<import("./utils/geo.js").BBox>;
39
30
  maxzoom: number;
40
31
  onprogress?: ((progress: TileDownloadStats) => void) | undefined;
41
32
  trackErrors?: boolean | undefined;
42
- sourceBounds?: BBox | undefined;
33
+ sourceBounds?: readonly [number, number, number, number] | undefined;
43
34
  boundsBuffer?: boolean | undefined;
44
35
  minzoom?: number | undefined;
45
36
  concurrency?: number | undefined;
@@ -54,15 +45,15 @@ declare function downloadTiles({ tileUrls, bounds, maxzoom, onprogress, trackErr
54
45
  /**
55
46
  *
56
47
  * @param {object} opts
57
- * @param {import('./utils/geo.js').BBox} [opts.bounds]
58
- * @param {import('./utils/geo.js').BBox} [opts.sourceBounds]
48
+ * @param {Readonly<import('./utils/geo.js').BBox>} [opts.bounds]
49
+ * @param {Readonly<import('./utils/geo.js').BBox>} [opts.sourceBounds]
59
50
  * @param {boolean} [opts.boundsBuffer]
60
51
  * @param {number} [opts.minzoom]
61
52
  * @param {number} opts.maxzoom
62
53
  */
63
- declare function tileIterator({ bounds, minzoom, maxzoom, sourceBounds, boundsBuffer, }: {
64
- bounds?: BBox | undefined;
65
- sourceBounds?: BBox | undefined;
54
+ export function tileIterator({ bounds, minzoom, maxzoom, sourceBounds, boundsBuffer, }: {
55
+ bounds?: readonly [number, number, number, number] | undefined;
56
+ sourceBounds?: readonly [number, number, number, number] | undefined;
66
57
  boundsBuffer?: boolean | undefined;
67
58
  minzoom?: number | undefined;
68
59
  maxzoom: number;
@@ -71,12 +62,11 @@ declare function tileIterator({ bounds, minzoom, maxzoom, sourceBounds, boundsBu
71
62
  y: number;
72
63
  z: number;
73
64
  }, void, unknown>;
74
- type TileInfo = Omit<TileInfo$1, "sourceId">;
75
- type TileDownloadStats = {
65
+ export type TileInfo = Omit<import("./writer.js").TileInfo, "sourceId">;
66
+ export type TileDownloadStats = {
76
67
  total: number;
77
68
  downloaded: number;
78
69
  skipped: number;
79
70
  totalBytes: number;
80
71
  };
81
-
82
- export { type TileDownloadStats, type TileInfo, downloadTiles, tileIterator };
72
+ import { FetchQueue } from './utils/fetch.js';
@@ -0,0 +1,61 @@
1
+ import type { SourceSpecification, StyleSpecification, ValidationError, GeoJSONSourceSpecification, VectorSourceSpecification, RasterSourceSpecification, RasterDEMSourceSpecification } from '@maplibre/maplibre-gl-style-spec';
2
+ import type { GeoJSON, BBox } from 'geojson';
3
+ import type { SetRequired } from 'type-fest';
4
+ import { SUPPORTED_SOURCE_TYPES } from './writer.js';
5
+ export type InputSource = Extract<SourceSpecification, {
6
+ type: (typeof SUPPORTED_SOURCE_TYPES)[number];
7
+ }>;
8
+ type TransformInlinedSource<T extends SourceSpecification> = T extends GeoJSONSourceSpecification ? OmitUnion<T, 'data'> & {
9
+ data: GeoJSON;
10
+ } : T extends VectorSourceSpecification | RasterSourceSpecification | RasterDEMSourceSpecification ? SetRequired<OmitUnion<T, 'url'>, 'tiles'> : T;
11
+ /**
12
+ * This is a slightly stricter version of SourceSpecification that requires
13
+ * sources to be inlined (e.g. no urls to TileJSON or GeoJSON files).
14
+ */
15
+ export type InlinedSource = TransformInlinedSource<SourceSpecification>;
16
+ type SupportedInlinedSource = Extract<InlinedSource, {
17
+ type: (typeof SUPPORTED_SOURCE_TYPES)[number];
18
+ }>;
19
+ /**
20
+ * This is a slightly stricter version of StyleSpecification that requires
21
+ * sources to be inlined (e.g. no urls to TileJSON or GeoJSON files).
22
+ */
23
+ export type StyleInlinedSources = Omit<StyleSpecification, 'sources'> & {
24
+ sources: {
25
+ [_: string]: InlinedSource;
26
+ };
27
+ };
28
+ export type SMPSource = TransformSMPInputSource<SupportedInlinedSource>;
29
+ /**
30
+ * This is a slightly stricter version of StyleSpecification that is provided in
31
+ * a Styled Map Package. Tile sources must have tile URLs inlined (they cannot
32
+ * refer to a TileJSON url), and they must have bounds, minzoom, and maxzoom.
33
+ * GeoJSON sources must have inlined GeoJSON (not a URL to a GeoJSON file).
34
+ */
35
+ export type SMPStyle = TransformSMPStyle<StyleSpecification>;
36
+ export type TransformSMPInputSource<T extends SupportedInlinedSource> = T extends GeoJSONSourceSpecification ? T & {
37
+ data: {
38
+ bbox: BBox;
39
+ };
40
+ } : T extends RasterSourceSpecification | VectorSourceSpecification ? SetRequired<T, 'bounds' | 'minzoom' | 'maxzoom'> : T;
41
+ type TransformSMPStyle<T extends StyleSpecification> = Omit<T, 'sources'> & {
42
+ metadata: {
43
+ 'smp:bounds': [number, number, number, number];
44
+ 'smp:maxzoom': 0;
45
+ 'smp:sourceFolders': {
46
+ [_: string]: string;
47
+ };
48
+ [key: string]: unknown;
49
+ };
50
+ sources: {
51
+ [_: string]: SMPSource;
52
+ };
53
+ };
54
+ export interface ValidateStyle {
55
+ (style: unknown): style is StyleSpecification;
56
+ errors: Array<ValidationError>;
57
+ }
58
+ export type DownloadStream = ReadableStream<Uint8Array>;
59
+ export type RequiredUnion<T> = T extends any ? Required<T> : never;
60
+ export type OmitUnion<T, K extends keyof any> = T extends unknown ? Omit<T, K> : never;
61
+ export {};
@@ -5,14 +5,12 @@
5
5
  * @param {unknown} error
6
6
  * @returns {error is Error & { code: 'ENOENT' | 'EPERM' }}
7
7
  */
8
- declare function isFileNotThereError(error: unknown): error is Error & {
8
+ export function isFileNotThereError(error: unknown): error is Error & {
9
9
  code: "ENOENT" | "EPERM";
10
10
  };
11
- declare class ENOENT extends Error {
11
+ export class ENOENT extends Error {
12
12
  /** @param {string} path */
13
13
  constructor(path: string);
14
14
  code: string;
15
15
  path: string;
16
16
  }
17
-
18
- export { ENOENT, isFileNotThereError };
@@ -1,6 +1,3 @@
1
- import { ProgressCallback } from './streams.js';
2
- import 'stream/web';
3
-
4
1
  /**
5
2
  * @typedef {object} DownloadResponse
6
3
  * @property {ReadableStream<Uint8Array>} body Web ReadableStream of the response body
@@ -10,7 +7,7 @@ import 'stream/web';
10
7
  /**
11
8
  * A wrapper for fetch that limits the number of concurrent downloads.
12
9
  */
13
- declare class FetchQueue {
10
+ export class FetchQueue {
14
11
  /** @param {number} concurrency */
15
12
  constructor(concurrency: number);
16
13
  get activeCount(): number;
@@ -28,11 +25,11 @@ declare class FetchQueue {
28
25
  * @returns {Promise<DownloadResponse>}
29
26
  */
30
27
  fetch(url: string, { onprogress }?: {
31
- onprogress?: ProgressCallback;
28
+ onprogress?: import("./streams.js").ProgressCallback;
32
29
  }): Promise<DownloadResponse>;
33
30
  #private;
34
31
  }
35
- type DownloadResponse = {
32
+ export type DownloadResponse = {
36
33
  /**
37
34
  * Web ReadableStream of the response body
38
35
  */
@@ -46,5 +43,3 @@ type DownloadResponse = {
46
43
  */
47
44
  contentLength: number | null;
48
45
  };
49
-
50
- export { type DownloadResponse, FetchQueue };