styled-map-package 2.2.1 → 4.0.0

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 (107) hide show
  1. package/bin/smp-download.js +3 -3
  2. package/bin/smp-mbtiles.js +1 -1
  3. package/bin/smp-view.js +15 -4
  4. package/dist/download.cjs +101 -0
  5. package/dist/download.d.cts +65 -0
  6. package/dist/{lib/download.d.ts → download.d.ts} +22 -6
  7. package/dist/download.js +77 -0
  8. package/dist/from-mbtiles.cjs +91 -0
  9. package/dist/from-mbtiles.d.cts +17 -0
  10. package/dist/from-mbtiles.d.ts +17 -0
  11. package/dist/from-mbtiles.js +57 -0
  12. package/dist/index.cjs +49 -0
  13. package/dist/index.d.cts +27 -0
  14. package/dist/index.d.ts +27 -0
  15. package/dist/index.js +18 -0
  16. package/dist/reader-watch.cjs +135 -0
  17. package/dist/reader-watch.d.cts +24 -0
  18. package/dist/reader-watch.d.ts +24 -0
  19. package/dist/reader-watch.js +101 -0
  20. package/dist/reader.cjs +167 -0
  21. package/dist/reader.d.cts +62 -0
  22. package/dist/{lib/reader.d.ts → reader.d.ts} +16 -5
  23. package/dist/reader.js +138 -0
  24. package/dist/reporters.cjs +122 -0
  25. package/dist/reporters.d.cts +10 -0
  26. package/dist/{lib/reporters.d.ts → reporters.d.ts} +5 -2
  27. package/dist/reporters.js +88 -0
  28. package/dist/server.cjs +79 -0
  29. package/dist/server.d.cts +48 -0
  30. package/dist/server.d.ts +48 -0
  31. package/dist/server.js +55 -0
  32. package/dist/style-downloader.cjs +312 -0
  33. package/dist/style-downloader.d.cts +120 -0
  34. package/dist/{lib/style-downloader.d.ts → style-downloader.d.ts} +23 -13
  35. package/dist/style-downloader.js +288 -0
  36. package/dist/tile-downloader.cjs +158 -0
  37. package/dist/tile-downloader.d.cts +84 -0
  38. package/dist/{lib/tile-downloader.d.ts → tile-downloader.d.ts} +22 -10
  39. package/dist/tile-downloader.js +126 -0
  40. package/dist/{lib/writer.d.ts → types-B4Xn1F9K.d.cts} +74 -14
  41. package/dist/types-B4Xn1F9K.d.ts +189 -0
  42. package/dist/utils/errors.cjs +41 -0
  43. package/dist/utils/errors.d.cts +18 -0
  44. package/dist/{lib/utils → utils}/errors.d.ts +4 -2
  45. package/dist/utils/errors.js +16 -0
  46. package/dist/utils/fetch.cjs +96 -0
  47. package/dist/utils/fetch.d.cts +51 -0
  48. package/dist/{lib/utils → utils}/fetch.d.ts +10 -4
  49. package/dist/utils/fetch.js +62 -0
  50. package/dist/utils/file-formats.cjs +98 -0
  51. package/dist/utils/file-formats.d.cts +35 -0
  52. package/dist/{lib/utils → utils}/file-formats.d.ts +13 -3
  53. package/dist/utils/file-formats.js +62 -0
  54. package/dist/utils/geo.cjs +84 -0
  55. package/dist/utils/geo.d.cts +46 -0
  56. package/dist/{lib/utils → utils}/geo.d.ts +8 -6
  57. package/dist/utils/geo.js +56 -0
  58. package/dist/utils/mapbox.cjs +121 -0
  59. package/dist/utils/mapbox.d.cts +43 -0
  60. package/dist/utils/mapbox.d.ts +43 -0
  61. package/dist/utils/mapbox.js +91 -0
  62. package/dist/utils/misc.cjs +39 -0
  63. package/{lib/utils/misc.js → dist/utils/misc.d.cts} +5 -9
  64. package/dist/{lib/utils → utils}/misc.d.ts +5 -3
  65. package/dist/utils/misc.js +13 -0
  66. package/dist/utils/streams.cjs +130 -0
  67. package/dist/utils/streams.d.cts +73 -0
  68. package/dist/{lib/utils → utils}/streams.d.ts +14 -10
  69. package/dist/utils/streams.js +103 -0
  70. package/dist/utils/style.cjs +126 -0
  71. package/dist/utils/style.d.cts +69 -0
  72. package/dist/{lib/utils → utils}/style.d.ts +19 -9
  73. package/dist/utils/style.js +98 -0
  74. package/dist/utils/templates.cjs +114 -0
  75. package/dist/utils/templates.d.cts +78 -0
  76. package/dist/{lib/utils → utils}/templates.d.ts +24 -14
  77. package/dist/utils/templates.js +79 -0
  78. package/dist/writer.cjs +401 -0
  79. package/dist/writer.d.cts +7 -0
  80. package/dist/writer.d.ts +7 -0
  81. package/dist/writer.js +374 -0
  82. package/package.json +107 -41
  83. package/dist/lib/from-mbtiles.d.ts +0 -13
  84. package/dist/lib/index.d.ts +0 -10
  85. package/dist/lib/reader-watch.d.ts +0 -13
  86. package/dist/lib/server.d.ts +0 -15
  87. package/dist/lib/types.d.ts +0 -64
  88. package/dist/lib/utils/mapbox.d.ts +0 -41
  89. package/lib/download.js +0 -114
  90. package/lib/from-mbtiles.js +0 -83
  91. package/lib/index.js +0 -11
  92. package/lib/reader-watch.js +0 -133
  93. package/lib/reader.js +0 -165
  94. package/lib/reporters.js +0 -92
  95. package/lib/server.js +0 -81
  96. package/lib/style-downloader.js +0 -363
  97. package/lib/tile-downloader.js +0 -188
  98. package/lib/types.ts +0 -104
  99. package/lib/utils/errors.js +0 -24
  100. package/lib/utils/fetch.js +0 -100
  101. package/lib/utils/file-formats.js +0 -85
  102. package/lib/utils/geo.js +0 -87
  103. package/lib/utils/mapbox.js +0 -155
  104. package/lib/utils/streams.js +0 -165
  105. package/lib/utils/style.js +0 -174
  106. package/lib/utils/templates.js +0 -136
  107. package/lib/writer.js +0 -478
@@ -0,0 +1,288 @@
1
+ import { check as checkGeoJson } from "@placemarkio/check-geojson";
2
+ import { includeKeys } from "filter-obj";
3
+ import ky from "ky";
4
+ import Queue from "yocto-queue";
5
+ import zlib from "zlib";
6
+ import { downloadTiles } from "./tile-downloader.js";
7
+ import { FetchQueue } from "./utils/fetch.js";
8
+ import {
9
+ normalizeGlyphsURL,
10
+ normalizeSourceURL,
11
+ normalizeSpriteURL,
12
+ normalizeStyleURL
13
+ } from "./utils/mapbox.js";
14
+ import { clone, noop } from "./utils/misc.js";
15
+ import {
16
+ assertTileJSON,
17
+ isInlinedSource,
18
+ mapFontStacks,
19
+ validateStyle
20
+ } from "./utils/style.js";
21
+ class StyleDownloader {
22
+ /** @type {null | string} */
23
+ #styleURL = null;
24
+ /** @type {null | StyleSpecification} */
25
+ #inputStyle = null;
26
+ /** @type {FetchQueue} */
27
+ #fetchQueue;
28
+ #mapboxAccessToken;
29
+ /**
30
+ * @param {string | StyleSpecification} style A url to a style JSON file or a style object
31
+ * @param {object} [opts]
32
+ * @param {number} [opts.concurrency=8]
33
+ * @param {string} [opts.mapboxAccessToken] Downloading a style from Mapbox requires an access token
34
+ */
35
+ constructor(style, { concurrency = 8, mapboxAccessToken } = {}) {
36
+ if (typeof style === "string") {
37
+ const { searchParams } = new URL(style);
38
+ this.#mapboxAccessToken = searchParams.get("access_token") || mapboxAccessToken;
39
+ this.#styleURL = normalizeStyleURL(style, this.#mapboxAccessToken);
40
+ } else if (validateStyle(style)) {
41
+ this.#inputStyle = clone(style);
42
+ } else {
43
+ throw new AggregateError(validateStyle.errors, "Invalid style");
44
+ }
45
+ this.#fetchQueue = new FetchQueue(concurrency);
46
+ }
47
+ /**
48
+ * Number of active downloads.
49
+ */
50
+ get active() {
51
+ return this.#fetchQueue.activeCount;
52
+ }
53
+ /**
54
+ * Download the style JSON for this style and inline the sources
55
+ *
56
+ * @returns {Promise<StyleInlinedSources>}
57
+ */
58
+ async getStyle() {
59
+ if (!this.#inputStyle && this.#styleURL) {
60
+ const downloadedStyle = await ky(this.#styleURL).json();
61
+ if (!validateStyle(downloadedStyle)) {
62
+ throw new AggregateError(
63
+ validateStyle.errors,
64
+ "Invalid style: " + this.#styleURL
65
+ );
66
+ }
67
+ this.#inputStyle = downloadedStyle;
68
+ } else if (!this.#inputStyle) {
69
+ throw new Error("Unexpected state: no style or style URL provided");
70
+ }
71
+ const inlinedSources = {};
72
+ for (const [sourceId, source] of Object.entries(this.#inputStyle.sources)) {
73
+ inlinedSources[sourceId] = await this.#getInlinedSource(source);
74
+ }
75
+ return {
76
+ ...this.#inputStyle,
77
+ sources: inlinedSources
78
+ };
79
+ }
80
+ /**
81
+ * @param {SourceSpecification} source
82
+ * @returns {Promise<InlinedSource>}
83
+ */
84
+ async #getInlinedSource(source) {
85
+ if (isInlinedSource(source)) {
86
+ return source;
87
+ }
88
+ if (source.type === "raster" || source.type === "vector" || source.type === "raster-dem") {
89
+ if (!source.url) {
90
+ throw new Error("Source is missing both url and tiles properties");
91
+ }
92
+ const sourceUrl = normalizeSourceURL(source.url, this.#mapboxAccessToken);
93
+ const tilejson = await ky(sourceUrl).json();
94
+ assertTileJSON(tilejson);
95
+ return {
96
+ ...source,
97
+ ...includeKeys(tilejson, [
98
+ "bounds",
99
+ "maxzoom",
100
+ "minzoom",
101
+ "tiles",
102
+ "description",
103
+ "attribution",
104
+ "vector_layers"
105
+ ])
106
+ };
107
+ } else if (source.type === "geojson") {
108
+ if (typeof source.data !== "string") {
109
+ throw new Error("Unexpected data property for GeoJson source");
110
+ }
111
+ const geojsonUrl = normalizeSourceURL(
112
+ source.data,
113
+ this.#mapboxAccessToken
114
+ );
115
+ const data = checkGeoJson(await ky(geojsonUrl).text());
116
+ return {
117
+ ...source,
118
+ data
119
+ };
120
+ }
121
+ return source;
122
+ }
123
+ /**
124
+ * Download the sprite PNGs and JSON files for this style. Returns an async
125
+ * generator of json and png readable streams, and the sprite id and pixel
126
+ * ratio. Downloads pixel ratios `1` and `2`.
127
+ *
128
+ * @returns {AsyncGenerator<{ json: import('stream').Readable, png: import('stream').Readable, id: string, pixelRatio: number }>}
129
+ */
130
+ async *getSprites() {
131
+ const style = await this.getStyle();
132
+ if (!style.sprite) return;
133
+ const accessToken = this.#mapboxAccessToken;
134
+ const spriteDefs = Array.isArray(style.sprite) ? style.sprite : [{ id: "default", url: style.sprite }];
135
+ for (const { id, url } of spriteDefs) {
136
+ for (const pixelRatio of [1, 2]) {
137
+ const format = pixelRatio === 1 ? "" : "@2x";
138
+ const jsonUrl = normalizeSpriteURL(url, format, ".json", accessToken);
139
+ const pngUrl = normalizeSpriteURL(url, format, ".png", accessToken);
140
+ const [{ body: json }, { body: png }] = await Promise.all([
141
+ this.#fetchQueue.fetch(jsonUrl),
142
+ this.#fetchQueue.fetch(pngUrl)
143
+ ]);
144
+ yield { json, png, id, pixelRatio };
145
+ }
146
+ }
147
+ }
148
+ /**
149
+ * Download all the glyphs for the fonts used in this style. When font stacks
150
+ * are used in the style.json (e.g. lists of prefered fonts like with CSS),
151
+ * then the first font in the stack is downloaded. Defaults to downloading all
152
+ * UTF character ranges, which may be overkill for some styles. TODO: add more
153
+ * options here.
154
+ *
155
+ * Returns an async generator of readable streams of glyph data and glyph info
156
+ * objects.
157
+ *
158
+ * @param {object} opts
159
+ * @param {(progress: GlyphDownloadStats) => void} [opts.onprogress]
160
+ * @returns {AsyncGenerator<[import('stream').Readable, GlyphInfo]>}
161
+ */
162
+ async *getGlyphs({ onprogress = noop } = {}) {
163
+ const style = await this.getStyle();
164
+ if (!style.glyphs) return;
165
+ let completed = 0;
166
+ let stats = {
167
+ total: 0,
168
+ downloaded: 0,
169
+ totalBytes: 0
170
+ };
171
+ function onDownloadProgress({ chunkBytes }) {
172
+ stats.totalBytes += chunkBytes;
173
+ onprogress(stats);
174
+ }
175
+ function onDownloadComplete() {
176
+ stats.downloaded = ++completed;
177
+ onprogress(stats);
178
+ }
179
+ const queue = new Queue();
180
+ const fontStacks = /* @__PURE__ */ new Map();
181
+ mapFontStacks(style.layers, (fontStack) => {
182
+ fontStacks.set(fontStack[0], fontStack.join(","));
183
+ return [];
184
+ });
185
+ const glyphUrl = normalizeGlyphsURL(style.glyphs, this.#mapboxAccessToken);
186
+ for (const [font, fontStack] of fontStacks.entries()) {
187
+ for (let i = 0; i < Math.pow(2, 16); i += 256) {
188
+ const range = `${i}-${i + 255}`;
189
+ const url = glyphUrl.replace("{fontstack}", fontStack).replace("{range}", range);
190
+ const result = this.#fetchQueue.fetch(url, { onprogress: onDownloadProgress }).catch(noop);
191
+ queue.enqueue([result, { font, range }]);
192
+ }
193
+ }
194
+ stats.total = queue.size;
195
+ if (onprogress) onprogress(stats);
196
+ for (const [result, glyphInfo] of queue) {
197
+ const downloadResponse = await result.catch(noop);
198
+ if (!downloadResponse) continue;
199
+ const { body } = downloadResponse;
200
+ const gzipper = zlib.createGzip();
201
+ body.on("error", (err) => gzipper.destroy(err));
202
+ body.on("end", onDownloadComplete);
203
+ yield [body.pipe(gzipper), glyphInfo];
204
+ }
205
+ }
206
+ /**
207
+ * Get all the tiles for this style within the given bounds and zoom range.
208
+ * Returns an async generator of readable streams of tile data and tile info
209
+ * objects.
210
+ *
211
+ * The returned iterator also has a `skipped` property which is an
212
+ * array of tiles which could not be downloaded, and a `stats` property which
213
+ * is an object with the total number of tiles, downloaded tiles, and total
214
+ * bytes downloaded.
215
+ *
216
+ * @param {object} opts
217
+ * @param {import('./utils/geo.js').BBox} opts.bounds
218
+ * @param {number} opts.maxzoom
219
+ * @param {(progress: TileDownloadStats) => void} [opts.onprogress]
220
+ * @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.
221
+ * @returns {AsyncGenerator<[import('stream').Readable, TileInfo]> & { readonly skipped: Array<TileInfo & { error?: Error }>, readonly stats: TileDownloadStats }}
222
+ */
223
+ getTiles({ bounds, maxzoom, onprogress = noop, trackErrors = false }) {
224
+ const _this = this;
225
+ const skipped = [];
226
+ let stats = {
227
+ total: 0,
228
+ downloaded: 0,
229
+ skipped: 0,
230
+ totalBytes: 0
231
+ };
232
+ const tiles = async function* () {
233
+ const inlinedStyle = await _this.getStyle();
234
+ for await (const [sourceId, source] of Object.entries(
235
+ inlinedStyle.sources
236
+ )) {
237
+ if (source.type !== "raster" && source.type !== "vector") {
238
+ continue;
239
+ }
240
+ const statsBaseline = { ...stats };
241
+ const sourceTiles = downloadTiles({
242
+ tileUrls: source.tiles,
243
+ bounds,
244
+ maxzoom: Math.min(maxzoom, source.maxzoom || maxzoom),
245
+ minzoom: source.minzoom,
246
+ sourceBounds: source.bounds,
247
+ boundsBuffer: true,
248
+ scheme: source.scheme,
249
+ fetchQueue: _this.#fetchQueue,
250
+ onprogress: (sourceStats) => {
251
+ stats = addStats(statsBaseline, sourceStats);
252
+ onprogress(stats);
253
+ },
254
+ trackErrors
255
+ });
256
+ for await (const [tileDataStream, tileInfo] of sourceTiles) {
257
+ yield [tileDataStream, { ...tileInfo, sourceId }];
258
+ }
259
+ Array.prototype.push.apply(
260
+ skipped,
261
+ sourceTiles.skipped.map((tile) => ({ ...tile, sourceId }))
262
+ );
263
+ }
264
+ }();
265
+ Object.defineProperty(tiles, "skipped", {
266
+ get() {
267
+ return skipped;
268
+ }
269
+ });
270
+ Object.defineProperty(tiles, "stats", {
271
+ get() {
272
+ return stats;
273
+ }
274
+ });
275
+ return tiles;
276
+ }
277
+ }
278
+ function addStats(statsA, statsB) {
279
+ return {
280
+ total: statsA.total + statsB.total,
281
+ downloaded: statsA.downloaded + statsB.downloaded,
282
+ skipped: statsA.skipped + statsB.skipped,
283
+ totalBytes: statsA.totalBytes + statsB.totalBytes
284
+ };
285
+ }
286
+ export {
287
+ StyleDownloader
288
+ };
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var tile_downloader_exports = {};
30
+ __export(tile_downloader_exports, {
31
+ downloadTiles: () => downloadTiles,
32
+ tileIterator: () => tileIterator
33
+ });
34
+ module.exports = __toCommonJS(tile_downloader_exports);
35
+ var import_sphericalmercator = __toESM(require("@mapbox/sphericalmercator"), 1);
36
+ var import_yocto_queue = __toESM(require("yocto-queue"), 1);
37
+ var import_zlib = __toESM(require("zlib"), 1);
38
+ var import_fetch = require('./utils/fetch.cjs');
39
+ var import_file_formats = require('./utils/file-formats.cjs');
40
+ var import_geo = require('./utils/geo.cjs');
41
+ var import_misc = require('./utils/misc.cjs');
42
+ function downloadTiles({
43
+ tileUrls,
44
+ bounds,
45
+ maxzoom,
46
+ onprogress = import_misc.noop,
47
+ trackErrors = false,
48
+ sourceBounds = import_geo.MAX_BOUNDS,
49
+ boundsBuffer = false,
50
+ minzoom = 0,
51
+ concurrency = 8,
52
+ fetchQueue = new import_fetch.FetchQueue(concurrency),
53
+ scheme = "xyz"
54
+ }) {
55
+ const skipped = [];
56
+ let completed = 0;
57
+ let stats = {
58
+ total: 0,
59
+ downloaded: 0,
60
+ skipped: 0,
61
+ totalBytes: 0
62
+ };
63
+ function onDownloadProgress({ chunkBytes }) {
64
+ stats.totalBytes += chunkBytes;
65
+ onprogress(stats);
66
+ }
67
+ function onDownloadError(error, tileInfo) {
68
+ if (trackErrors) {
69
+ skipped.push({ ...tileInfo, error });
70
+ } else {
71
+ skipped.push(tileInfo);
72
+ }
73
+ onprogress(stats);
74
+ }
75
+ function onDownloadComplete() {
76
+ stats.downloaded = ++completed - skipped.length;
77
+ stats.skipped = skipped.length;
78
+ onprogress(stats);
79
+ }
80
+ const tiles = async function* () {
81
+ const queue = new import_yocto_queue.default();
82
+ const tiles2 = tileIterator({
83
+ bounds,
84
+ minzoom,
85
+ maxzoom,
86
+ sourceBounds,
87
+ boundsBuffer
88
+ });
89
+ for (const { x, y, z } of tiles2) {
90
+ const tileURL = (0, import_geo.getTileUrl)(tileUrls, { x, y, z, scheme });
91
+ const tileInfo = { z, x, y };
92
+ const result = fetchQueue.fetch(tileURL, { onprogress: onDownloadProgress }).catch((err) => onDownloadError(err, tileInfo));
93
+ queue.enqueue([result, tileInfo]);
94
+ }
95
+ stats.total = queue.size;
96
+ if (onprogress) onprogress(stats);
97
+ for (const [result, tileInfo] of queue) {
98
+ const downloadResponse = await result.catch(import_misc.noop);
99
+ if (!downloadResponse) continue;
100
+ let { body, mimeType } = downloadResponse;
101
+ body.on("end", onDownloadComplete);
102
+ body.on("error", (err) => onDownloadError(err, tileInfo));
103
+ let format;
104
+ if (mimeType) {
105
+ format = (0, import_file_formats.getFormatFromMimeType)(mimeType);
106
+ } else {
107
+ ;
108
+ [format, body] = await (0, import_file_formats.getTileFormatFromStream)(body);
109
+ }
110
+ let stream = body;
111
+ if (format === "mvt") {
112
+ const gzipStream = import_zlib.default.createGzip();
113
+ stream = body.pipe(gzipStream);
114
+ stream.on("error", (err) => gzipStream.destroy(err));
115
+ }
116
+ yield [stream, { ...tileInfo, format }];
117
+ }
118
+ }();
119
+ Object.defineProperty(tiles, "skipped", {
120
+ get() {
121
+ return skipped;
122
+ }
123
+ });
124
+ Object.defineProperty(tiles, "stats", {
125
+ get() {
126
+ return stats;
127
+ }
128
+ });
129
+ return tiles;
130
+ }
131
+ function* tileIterator({
132
+ bounds = [...import_geo.MAX_BOUNDS],
133
+ minzoom = 0,
134
+ maxzoom,
135
+ sourceBounds,
136
+ boundsBuffer = false
137
+ }) {
138
+ const sm = new import_sphericalmercator.default({ size: 256 });
139
+ for (let z = minzoom; z <= maxzoom; z++) {
140
+ let { minX, minY, maxX, maxY } = sm.xyz([...bounds], z);
141
+ let sourceXYBounds = sourceBounds ? sm.xyz([...sourceBounds], z) : { minX, minY, maxX, maxY };
142
+ const buffer = boundsBuffer ? 1 : 0;
143
+ minX = Math.max(0, minX - buffer, sourceXYBounds.minX);
144
+ minY = Math.max(0, minY - buffer, sourceXYBounds.minY);
145
+ maxX = Math.min(Math.pow(2, z) - 1, maxX + buffer, sourceXYBounds.maxX);
146
+ maxY = Math.min(Math.pow(2, z) - 1, maxY + buffer, sourceXYBounds.maxY);
147
+ for (let x = minX; x <= maxX; x++) {
148
+ for (let y = minY; y <= maxY; y++) {
149
+ yield { x, y, z };
150
+ }
151
+ }
152
+ }
153
+ }
154
+ // Annotate the CommonJS export names for ESM import in node:
155
+ 0 && (module.exports = {
156
+ downloadTiles,
157
+ tileIterator
158
+ });
@@ -0,0 +1,84 @@
1
+ import { T as TileInfo$1 } from './types-B4Xn1F9K.cjs';
2
+ import * as stream from 'stream';
3
+ import { BBox } from './utils/geo.cjs';
4
+ import { FetchQueue } from './utils/fetch.cjs';
5
+ import '@maplibre/maplibre-gl-style-spec';
6
+ import 'geojson';
7
+ import 'type-fest';
8
+ import 'readable-stream';
9
+ import 'events';
10
+ import './utils/streams.cjs';
11
+
12
+ /** @typedef {Omit<import('./writer.js').TileInfo, 'sourceId'>} TileInfo */
13
+ /**
14
+ * @typedef {object} TileDownloadStats
15
+ * @property {number} total
16
+ * @property {number} downloaded
17
+ * @property {number} skipped
18
+ * @property {number} totalBytes
19
+ */
20
+ /**
21
+ * Download tiles from a list of tile URLs within a bounding box and zoom range.
22
+ * Returns an async generator of tile data as readable streams and tile info objects.
23
+ *
24
+ * @param {object} opts
25
+ * @param {string[]} opts.tileUrls Array of tile URL templates. Use `{x}`, `{y}`, `{z}` placeholders, and optional `{scheme}` placeholder which can be `xyz` or `tms`.
26
+ * @param {import('./utils/geo.js').BBox} opts.bounds Bounding box of the area to download
27
+ * @param {number} opts.maxzoom Maximum zoom level to download
28
+ * @param {(progress: TileDownloadStats) => void} [opts.onprogress] Callback to report download progress
29
+ * @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.
30
+ * @param {import('./utils/geo.js').BBox} [opts.sourceBounds=MAX_BOUNDS] Bounding box of source data.
31
+ * @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.
32
+ * @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)
33
+ * @param {number} [opts.concurrency=8] Number of concurrent downloads (ignored if `fetchQueue` is provided)
34
+ * @param {FetchQueue} [opts.fetchQueue=new FetchQueue(concurrency)] Optional fetch queue to use for downloading tiles
35
+ * @param {'xyz' | 'tms'} [opts.scheme='xyz'] Tile scheme to use for tile URLs
36
+ * @returns {AsyncGenerator<[import('stream').Readable, TileInfo]> & { readonly skipped: Array<TileInfo & { error?: Error }>, readonly stats: TileDownloadStats }}
37
+ */
38
+ declare function downloadTiles({ tileUrls, bounds, maxzoom, onprogress, trackErrors, sourceBounds, boundsBuffer, minzoom, concurrency, fetchQueue, scheme, }: {
39
+ tileUrls: string[];
40
+ bounds: BBox;
41
+ maxzoom: number;
42
+ onprogress?: ((progress: TileDownloadStats) => void) | undefined;
43
+ trackErrors?: boolean | undefined;
44
+ sourceBounds?: BBox | undefined;
45
+ boundsBuffer?: boolean | undefined;
46
+ minzoom?: number | undefined;
47
+ concurrency?: number | undefined;
48
+ fetchQueue?: FetchQueue | undefined;
49
+ scheme?: "xyz" | "tms" | undefined;
50
+ }): AsyncGenerator<[stream.Readable, TileInfo]> & {
51
+ readonly skipped: Array<TileInfo & {
52
+ error?: Error;
53
+ }>;
54
+ readonly stats: TileDownloadStats;
55
+ };
56
+ /**
57
+ *
58
+ * @param {object} opts
59
+ * @param {import('./utils/geo.js').BBox} [opts.bounds]
60
+ * @param {import('./utils/geo.js').BBox} [opts.sourceBounds]
61
+ * @param {boolean} [opts.boundsBuffer]
62
+ * @param {number} [opts.minzoom]
63
+ * @param {number} opts.maxzoom
64
+ */
65
+ declare function tileIterator({ bounds, minzoom, maxzoom, sourceBounds, boundsBuffer, }: {
66
+ bounds?: BBox | undefined;
67
+ sourceBounds?: BBox | undefined;
68
+ boundsBuffer?: boolean | undefined;
69
+ minzoom?: number | undefined;
70
+ maxzoom: number;
71
+ }): Generator<{
72
+ x: number;
73
+ y: number;
74
+ z: number;
75
+ }, void, unknown>;
76
+ type TileInfo = Omit<TileInfo$1, "sourceId">;
77
+ type TileDownloadStats = {
78
+ total: number;
79
+ downloaded: number;
80
+ skipped: number;
81
+ totalBytes: number;
82
+ };
83
+
84
+ export { type TileDownloadStats, type TileInfo, downloadTiles, tileIterator };
@@ -1,3 +1,14 @@
1
+ import { T as TileInfo$1 } from './types-B4Xn1F9K.js';
2
+ import * as stream from 'stream';
3
+ import { BBox } from './utils/geo.js';
4
+ import { FetchQueue } from './utils/fetch.js';
5
+ import '@maplibre/maplibre-gl-style-spec';
6
+ import 'geojson';
7
+ import 'type-fest';
8
+ import 'readable-stream';
9
+ import 'events';
10
+ import './utils/streams.js';
11
+
1
12
  /** @typedef {Omit<import('./writer.js').TileInfo, 'sourceId'>} TileInfo */
2
13
  /**
3
14
  * @typedef {object} TileDownloadStats
@@ -24,19 +35,19 @@
24
35
  * @param {'xyz' | 'tms'} [opts.scheme='xyz'] Tile scheme to use for tile URLs
25
36
  * @returns {AsyncGenerator<[import('stream').Readable, TileInfo]> & { readonly skipped: Array<TileInfo & { error?: Error }>, readonly stats: TileDownloadStats }}
26
37
  */
27
- export function downloadTiles({ tileUrls, bounds, maxzoom, onprogress, trackErrors, sourceBounds, boundsBuffer, minzoom, concurrency, fetchQueue, scheme, }: {
38
+ declare function downloadTiles({ tileUrls, bounds, maxzoom, onprogress, trackErrors, sourceBounds, boundsBuffer, minzoom, concurrency, fetchQueue, scheme, }: {
28
39
  tileUrls: string[];
29
- bounds: import("./utils/geo.js").BBox;
40
+ bounds: BBox;
30
41
  maxzoom: number;
31
42
  onprogress?: ((progress: TileDownloadStats) => void) | undefined;
32
43
  trackErrors?: boolean | undefined;
33
- sourceBounds?: import("./utils/geo.js").BBox | undefined;
44
+ sourceBounds?: BBox | undefined;
34
45
  boundsBuffer?: boolean | undefined;
35
46
  minzoom?: number | undefined;
36
47
  concurrency?: number | undefined;
37
48
  fetchQueue?: FetchQueue | undefined;
38
49
  scheme?: "xyz" | "tms" | undefined;
39
- }): AsyncGenerator<[import("stream").Readable, TileInfo]> & {
50
+ }): AsyncGenerator<[stream.Readable, TileInfo]> & {
40
51
  readonly skipped: Array<TileInfo & {
41
52
  error?: Error;
42
53
  }>;
@@ -51,9 +62,9 @@ export function downloadTiles({ tileUrls, bounds, maxzoom, onprogress, trackErro
51
62
  * @param {number} [opts.minzoom]
52
63
  * @param {number} opts.maxzoom
53
64
  */
54
- export function tileIterator({ bounds, minzoom, maxzoom, sourceBounds, boundsBuffer, }: {
55
- bounds?: import("./utils/geo.js").BBox | undefined;
56
- sourceBounds?: import("./utils/geo.js").BBox | undefined;
65
+ declare function tileIterator({ bounds, minzoom, maxzoom, sourceBounds, boundsBuffer, }: {
66
+ bounds?: BBox | undefined;
67
+ sourceBounds?: BBox | undefined;
57
68
  boundsBuffer?: boolean | undefined;
58
69
  minzoom?: number | undefined;
59
70
  maxzoom: number;
@@ -62,11 +73,12 @@ export function tileIterator({ bounds, minzoom, maxzoom, sourceBounds, boundsBuf
62
73
  y: number;
63
74
  z: number;
64
75
  }, void, unknown>;
65
- export type TileInfo = Omit<import("./writer.js").TileInfo, "sourceId">;
66
- export type TileDownloadStats = {
76
+ type TileInfo = Omit<TileInfo$1, "sourceId">;
77
+ type TileDownloadStats = {
67
78
  total: number;
68
79
  downloaded: number;
69
80
  skipped: number;
70
81
  totalBytes: number;
71
82
  };
72
- import { FetchQueue } from './utils/fetch.js';
83
+
84
+ export { type TileDownloadStats, type TileInfo, downloadTiles, tileIterator };