styled-map-package-api 5.0.0-pre.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 (71) hide show
  1. package/dist/download.cjs +100 -0
  2. package/dist/download.d.cts +64 -0
  3. package/dist/download.d.ts +64 -0
  4. package/dist/download.js +76 -0
  5. package/dist/from-mbtiles.cjs +81 -0
  6. package/dist/from-mbtiles.d.cts +10 -0
  7. package/dist/from-mbtiles.d.ts +10 -0
  8. package/dist/from-mbtiles.js +57 -0
  9. package/dist/index.cjs +46 -0
  10. package/dist/index.d.cts +25 -0
  11. package/dist/index.d.ts +25 -0
  12. package/dist/index.js +16 -0
  13. package/dist/reader.cjs +287 -0
  14. package/dist/reader.d.cts +68 -0
  15. package/dist/reader.d.ts +68 -0
  16. package/dist/reader.js +259 -0
  17. package/dist/server.cjs +73 -0
  18. package/dist/server.d.cts +46 -0
  19. package/dist/server.d.ts +46 -0
  20. package/dist/server.js +49 -0
  21. package/dist/style-downloader.cjs +314 -0
  22. package/dist/style-downloader.d.cts +119 -0
  23. package/dist/style-downloader.d.ts +119 -0
  24. package/dist/style-downloader.js +290 -0
  25. package/dist/tile-downloader.cjs +156 -0
  26. package/dist/tile-downloader.d.cts +83 -0
  27. package/dist/tile-downloader.d.ts +83 -0
  28. package/dist/tile-downloader.js +124 -0
  29. package/dist/types-CJq90eOB.d.cts +184 -0
  30. package/dist/types-CJq90eOB.d.ts +184 -0
  31. package/dist/utils/errors.cjs +41 -0
  32. package/dist/utils/errors.d.cts +18 -0
  33. package/dist/utils/errors.d.ts +18 -0
  34. package/dist/utils/errors.js +16 -0
  35. package/dist/utils/fetch.cjs +97 -0
  36. package/dist/utils/fetch.d.cts +50 -0
  37. package/dist/utils/fetch.d.ts +50 -0
  38. package/dist/utils/fetch.js +63 -0
  39. package/dist/utils/file-formats.cjs +96 -0
  40. package/dist/utils/file-formats.d.cts +33 -0
  41. package/dist/utils/file-formats.d.ts +33 -0
  42. package/dist/utils/file-formats.js +70 -0
  43. package/dist/utils/geo.cjs +84 -0
  44. package/dist/utils/geo.d.cts +46 -0
  45. package/dist/utils/geo.d.ts +46 -0
  46. package/dist/utils/geo.js +56 -0
  47. package/dist/utils/mapbox.cjs +121 -0
  48. package/dist/utils/mapbox.d.cts +43 -0
  49. package/dist/utils/mapbox.d.ts +43 -0
  50. package/dist/utils/mapbox.js +91 -0
  51. package/dist/utils/misc.cjs +39 -0
  52. package/dist/utils/misc.d.cts +22 -0
  53. package/dist/utils/misc.d.ts +22 -0
  54. package/dist/utils/misc.js +13 -0
  55. package/dist/utils/streams.cjs +99 -0
  56. package/dist/utils/streams.d.cts +49 -0
  57. package/dist/utils/streams.d.ts +49 -0
  58. package/dist/utils/streams.js +73 -0
  59. package/dist/utils/style.cjs +126 -0
  60. package/dist/utils/style.d.cts +67 -0
  61. package/dist/utils/style.d.ts +67 -0
  62. package/dist/utils/style.js +98 -0
  63. package/dist/utils/templates.cjs +124 -0
  64. package/dist/utils/templates.d.cts +80 -0
  65. package/dist/utils/templates.d.ts +80 -0
  66. package/dist/utils/templates.js +85 -0
  67. package/dist/writer.cjs +465 -0
  68. package/dist/writer.d.cts +5 -0
  69. package/dist/writer.d.ts +5 -0
  70. package/dist/writer.js +452 -0
  71. package/package.json +161 -0
package/dist/writer.js ADDED
@@ -0,0 +1,452 @@
1
+ import { validateStyleMin, migrate } from "@maplibre/maplibre-gl-style-spec";
2
+ import { bbox } from "@turf/bbox";
3
+ import { EventEmitter } from "events";
4
+ import { excludeKeys } from "filter-obj";
5
+ import { ZipWriter } from "zip-writer";
6
+ import { getTileFormatFromStream } from "./utils/file-formats.js";
7
+ import { MAX_BOUNDS, tileToBBox, unionBBox } from "./utils/geo.js";
8
+ import { clone } from "./utils/misc.js";
9
+ import { writeStreamFromAsync } from "./utils/streams.js";
10
+ import { replaceFontStacks } from "./utils/style.js";
11
+ import {
12
+ FONTS_FOLDER,
13
+ FORMAT_VERSION,
14
+ getGlyphFilename,
15
+ getSpriteFilename,
16
+ getSpriteUri,
17
+ getTileFilename,
18
+ getTileUri,
19
+ GLYPH_URI,
20
+ SOURCES_FOLDER,
21
+ STYLE_FILE,
22
+ VERSION_FILE
23
+ } from "./utils/templates.js";
24
+ const SUPPORTED_SOURCE_TYPES = (
25
+ /** @type {const} */
26
+ [
27
+ "raster",
28
+ "vector",
29
+ "geojson"
30
+ ]
31
+ );
32
+ class Writer extends EventEmitter {
33
+ #zipWriter = new ZipWriter();
34
+ /** @type {Set<string>} */
35
+ #addedFiles = /* @__PURE__ */ new Set();
36
+ /** @type {Set<string>} */
37
+ #fonts = /* @__PURE__ */ new Set();
38
+ /** @type {Set<string>} */
39
+ #addedSpriteIds = /* @__PURE__ */ new Set();
40
+ /** @type {Map<string, SourceInfo>} */
41
+ #sources = /* @__PURE__ */ new Map();
42
+ /** @type {StyleSpecification} */
43
+ #style;
44
+ /** @type {ReadableStream<Uint8Array>} */
45
+ #outputStream;
46
+ /** @type {ReadableStreamDefaultController<Uint8Array>} */
47
+ #outputController;
48
+ static SUPPORTED_SOURCE_TYPES = SUPPORTED_SOURCE_TYPES;
49
+ /**
50
+ * @param {any} style A v7 or v8 MapLibre style. v7 styles will be migrated to
51
+ * v8. (There are currently no typescript declarations for v7 styles, hence
52
+ * this is typed as `any` and validated internally)
53
+ */
54
+ constructor(style) {
55
+ super();
56
+ if (!style || !("version" in style)) {
57
+ throw new Error("Invalid style");
58
+ }
59
+ if (style.version !== 7 && style.version !== 8) {
60
+ throw new Error(`Invalid style: Unsupported version v${style.version}`);
61
+ }
62
+ if (!Array.isArray(style.layers)) {
63
+ throw new Error("Invalid style: missing layers property");
64
+ }
65
+ const styleCopy = clone(style);
66
+ migrate(styleCopy);
67
+ const errors = validateStyleMin(styleCopy);
68
+ if (errors.length) {
69
+ throw new AggregateError(errors, "Invalid style");
70
+ }
71
+ this.#style = styleCopy;
72
+ for (const [sourceId, source] of Object.entries(this.#style.sources)) {
73
+ if (source.type !== "geojson") continue;
74
+ this.#addSource(sourceId, source);
75
+ }
76
+ const zipReader = this.#zipWriter.readable.getReader();
77
+ let outputController;
78
+ this.#outputStream = new ReadableStream({
79
+ start(controller) {
80
+ outputController = controller;
81
+ },
82
+ async pull(controller) {
83
+ try {
84
+ const { done, value } = await zipReader.read();
85
+ if (done) {
86
+ controller.close();
87
+ } else {
88
+ controller.enqueue(
89
+ /** @type {Uint8Array} */
90
+ value
91
+ );
92
+ }
93
+ } catch (err) {
94
+ controller.error(err);
95
+ }
96
+ },
97
+ cancel(reason) {
98
+ zipReader.cancel(reason);
99
+ }
100
+ });
101
+ this.#outputController = outputController;
102
+ }
103
+ /**
104
+ * @returns {ReadableStream<Uint8Array>} Readable stream of the styled map package
105
+ */
106
+ get outputStream() {
107
+ return this.#outputStream;
108
+ }
109
+ /**
110
+ * Abort the output stream with an error. Call this if an error occurs during
111
+ * writing to propagate the error to consumers of `outputStream`.
112
+ *
113
+ * @param {Error} reason
114
+ */
115
+ abort(reason) {
116
+ this.#outputController.error(reason);
117
+ }
118
+ #getBounds() {
119
+ let bounds;
120
+ let maxzoom = 0;
121
+ for (const { source } of this.#sources.values()) {
122
+ if (source.type === "geojson") {
123
+ if (isEmptyFeatureCollection(source.data)) continue;
124
+ const bbox2 = get2DBBox(source.data.bbox);
125
+ bounds = bounds ? unionBBox([bounds, bbox2]) : [...bbox2];
126
+ } else {
127
+ if (source.maxzoom < maxzoom) continue;
128
+ if (source.maxzoom === maxzoom) {
129
+ bounds = bounds ? unionBBox([bounds, source.bounds]) : source.bounds;
130
+ } else {
131
+ bounds = source.bounds;
132
+ maxzoom = source.maxzoom;
133
+ }
134
+ }
135
+ }
136
+ return bounds;
137
+ }
138
+ #getMaxZoom() {
139
+ let maxzoom = 0;
140
+ for (const { source } of this.#sources.values()) {
141
+ const sourceMaxzoom = (
142
+ // For GeoJSON sources, the maxzoom is 16 unless otherwise set
143
+ source.type === "geojson" ? source.maxzoom || 16 : source.maxzoom
144
+ );
145
+ maxzoom = Math.max(maxzoom, sourceMaxzoom);
146
+ }
147
+ return maxzoom;
148
+ }
149
+ /**
150
+ * Add a source definition to the styled map package
151
+ *
152
+ * @param {string} sourceId
153
+ * @param {InputSource} source
154
+ * @returns {SourceInfo}
155
+ */
156
+ #addSource(sourceId, source) {
157
+ const encodedSourceId = encodeSourceId(this.#sources.size);
158
+ const tileSourceOverrides = {
159
+ minzoom: 0,
160
+ maxzoom: 0,
161
+ bounds: (
162
+ /** @type {import('./utils/geo.js').BBox} */
163
+ [...MAX_BOUNDS]
164
+ ),
165
+ tiles: (
166
+ /** @type {string[]} */
167
+ []
168
+ )
169
+ };
170
+ let smpSource;
171
+ switch (source.type) {
172
+ case "raster":
173
+ case "vector":
174
+ smpSource = {
175
+ ...excludeKeys(source, ["tiles", "url"]),
176
+ ...tileSourceOverrides
177
+ };
178
+ break;
179
+ case "geojson":
180
+ smpSource = {
181
+ ...source,
182
+ maxzoom: 0,
183
+ data: typeof source.data !== "string" ? (
184
+ // Add a bbox property to the GeoJSON data if it doesn't already have one
185
+ { ...source.data, bbox: source.data.bbox || bbox(source.data) }
186
+ ) : (
187
+ // If GeoJSON data is referenced by a URL, start with an empty FeatureCollection
188
+ {
189
+ type: "FeatureCollection",
190
+ features: [],
191
+ bbox: [0, 0, 0, 0]
192
+ }
193
+ )
194
+ };
195
+ break;
196
+ }
197
+ const sourceInfo = {
198
+ source: smpSource,
199
+ encodedSourceId
200
+ };
201
+ this.#sources.set(sourceId, sourceInfo);
202
+ return sourceInfo;
203
+ }
204
+ /**
205
+ * Add a tile to the styled map package
206
+ *
207
+ * @param {Source} tileData
208
+ * @param {TileInfo} opts
209
+ */
210
+ async addTile(tileData, { z, x, y, sourceId, format }) {
211
+ let sourceInfo = this.#sources.get(sourceId);
212
+ if (!sourceInfo) {
213
+ const source2 = this.#style.sources[sourceId];
214
+ if (!source2) {
215
+ throw new Error(`Source not referenced in style.json: ${sourceId}`);
216
+ }
217
+ if (source2.type !== "raster" && source2.type !== "vector") {
218
+ throw new Error(`Unsupported source type: ${source2.type}`);
219
+ }
220
+ sourceInfo = this.#addSource(sourceId, source2);
221
+ }
222
+ const { source, encodedSourceId } = sourceInfo;
223
+ if (source.type !== "raster" && source.type !== "vector") {
224
+ throw new Error(`Unsupported source type: ${source.type}`);
225
+ }
226
+ if (!format) {
227
+ ;
228
+ [format, tileData] = await getTileFormatFromStream(toWebStream(tileData));
229
+ }
230
+ if (!sourceInfo.format) {
231
+ sourceInfo.format = format;
232
+ } else if (sourceInfo.format !== format) {
233
+ throw new Error(
234
+ `Tile format mismatch for source ${sourceId}: expected ${sourceInfo.format}, got ${format}`
235
+ );
236
+ }
237
+ const bbox2 = tileToBBox({ z, x, y });
238
+ if (z > source.maxzoom) {
239
+ source.maxzoom = z;
240
+ source.bounds = bbox2;
241
+ } else if (z === source.maxzoom) {
242
+ source.bounds = unionBBox([source.bounds, bbox2]);
243
+ }
244
+ const name = getTileFilename({ sourceId: encodedSourceId, z, x, y, format });
245
+ return this.#append(tileData, { name, store: true });
246
+ }
247
+ /**
248
+ * Create a write stream for adding tiles to the styled map package
249
+ *
250
+ * @param {object} opts
251
+ * @param {number} [opts.concurrency=16] The number of concurrent writes
252
+ *
253
+ * @returns
254
+ */
255
+ createTileWriteStream({ concurrency = 16 } = {}) {
256
+ return writeStreamFromAsync(this.addTile.bind(this), { concurrency });
257
+ }
258
+ /**
259
+ * Add a sprite to the styled map package
260
+ *
261
+ * @param {object} options
262
+ * @param {Source} options.json
263
+ * @param {Source} options.png
264
+ * @param {number} [options.pixelRatio]
265
+ * @param {string} [options.id='default']
266
+ * @returns {Promise<void>}
267
+ */
268
+ async addSprite({ json, png, pixelRatio = 1, id = "default" }) {
269
+ this.#addedSpriteIds.add(id);
270
+ const jsonName = getSpriteFilename({ id, pixelRatio, ext: ".json" });
271
+ const pngName = getSpriteFilename({ id, pixelRatio, ext: ".png" });
272
+ await Promise.all([
273
+ this.#append(json, { name: jsonName }),
274
+ this.#append(png, { name: pngName })
275
+ ]);
276
+ }
277
+ /**
278
+ * Add glyphs to the styled map package
279
+ *
280
+ * @param {Source} glyphData
281
+ * @param {GlyphInfo} glyphInfo
282
+ * @returns {Promise<void>}
283
+ */
284
+ addGlyphs(glyphData, { font: fontName, range }) {
285
+ this.#fonts.add(fontName);
286
+ const name = getGlyphFilename({ fontstack: fontName, range });
287
+ return this.#append(glyphData, { name });
288
+ }
289
+ /**
290
+ * Create a write stream for adding glyphs to the styled map package
291
+ *
292
+ * @param {object} opts
293
+ * @param {number} [opts.concurrency=16] The number of concurrent writes
294
+ * @returns
295
+ */
296
+ createGlyphWriteStream({ concurrency = 16 } = {}) {
297
+ return writeStreamFromAsync(this.addGlyphs.bind(this), { concurrency });
298
+ }
299
+ /**
300
+ * Finalize the styled map package and write the style to the archive.
301
+ * This method must be called to complete the archive.
302
+ * You must wait for your destination write stream to 'finish' before using the output.
303
+ */
304
+ async finish() {
305
+ await this.#append(FORMAT_VERSION, { name: VERSION_FILE });
306
+ this.#prepareStyle();
307
+ const style = JSON.stringify(this.#style);
308
+ await this.#append(style, { name: STYLE_FILE });
309
+ const entries = await this.#zipWriter.entries();
310
+ const sortedEntries = sortEntries(entries);
311
+ await this.#zipWriter.finalize({ entries: sortedEntries });
312
+ }
313
+ /**
314
+ * Mutates the style object to prepare it for writing to the archive.
315
+ * Deterministic: can be run more than once with the same result.
316
+ */
317
+ #prepareStyle() {
318
+ if (this.#sources.size === 0) {
319
+ throw new Error("Missing sources: add at least one source");
320
+ }
321
+ if (this.#style.glyphs && this.#fonts.size === 0) {
322
+ throw new Error(
323
+ "Missing fonts: style references glyphs but no fonts added"
324
+ );
325
+ }
326
+ replaceFontStacks(this.#style, [...this.#fonts]);
327
+ if (this.#style.glyphs) {
328
+ this.#style.glyphs = GLYPH_URI;
329
+ }
330
+ if (typeof this.#style.sprite === "string") {
331
+ if (!this.#addedSpriteIds.has("default")) {
332
+ throw new Error(
333
+ "Missing sprite: style references sprite but none added"
334
+ );
335
+ }
336
+ this.#style.sprite = getSpriteUri();
337
+ } else if (Array.isArray(this.#style.sprite)) {
338
+ this.#style.sprite = this.#style.sprite.map(({ id }) => {
339
+ if (!this.#addedSpriteIds.has(id)) {
340
+ throw new Error(
341
+ `Missing sprite: style references sprite ${id} but none added`
342
+ );
343
+ }
344
+ return { id, url: getSpriteUri(id) };
345
+ });
346
+ }
347
+ this.#style.sources = {};
348
+ for (const [sourceId, { source, encodedSourceId, format = "mvt" }] of this.#sources) {
349
+ if (source.type === "geojson" && isEmptyFeatureCollection(source.data)) {
350
+ continue;
351
+ }
352
+ this.#style.sources[sourceId] = source;
353
+ if (!("tiles" in source)) continue;
354
+ source.tiles = [getTileUri({ sourceId: encodedSourceId, format })];
355
+ }
356
+ this.#style.layers = this.#style.layers.filter(
357
+ (layer) => !("source" in layer) || !!this.#style.sources[layer.source]
358
+ );
359
+ const metadata = this.#style.metadata || (this.#style.metadata = {});
360
+ const bounds = this.#getBounds();
361
+ if (bounds) {
362
+ metadata["smp:bounds"] = bounds;
363
+ const [w, s, e, n] = bounds;
364
+ this.#style.center = [w + (e - w) / 2, s + (n - s) / 2];
365
+ }
366
+ metadata["smp:maxzoom"] = this.#getMaxZoom();
367
+ metadata["smp:sourceFolders"] = {};
368
+ for (const [sourceId, { encodedSourceId }] of this.#sources) {
369
+ metadata["smp:sourceFolders"][sourceId] = encodedSourceId;
370
+ }
371
+ this.#style.zoom = Math.max(0, this.#getMaxZoom() - 2);
372
+ }
373
+ /**
374
+ *
375
+ * @param {Source} source
376
+ * @param {{ name: string, store?: boolean }} options
377
+ * @returns {Promise<void>}
378
+ */
379
+ async #append(source, { name, store = false }) {
380
+ if (this.#addedFiles.has(name)) {
381
+ throw new Error(`${name} already added`);
382
+ }
383
+ this.#addedFiles.add(name);
384
+ const readable = toWebStream(source);
385
+ await this.#zipWriter.addEntry({ readable, name, store });
386
+ }
387
+ }
388
+ function encodeSourceId(sourceIndex) {
389
+ return sourceIndex.toString(36);
390
+ }
391
+ function toWebStream(source) {
392
+ if (typeof source === "string") {
393
+ const bytes = new TextEncoder().encode(source);
394
+ return new ReadableStream({
395
+ start(controller) {
396
+ controller.enqueue(bytes);
397
+ controller.close();
398
+ }
399
+ });
400
+ }
401
+ if (source instanceof Uint8Array) {
402
+ return new ReadableStream({
403
+ start(controller) {
404
+ controller.enqueue(
405
+ new Uint8Array(source.buffer, source.byteOffset, source.byteLength)
406
+ );
407
+ controller.close();
408
+ }
409
+ });
410
+ }
411
+ return (
412
+ /** @type {ReadableStream<Uint8Array>} */
413
+ source
414
+ );
415
+ }
416
+ function isEmptyFeatureCollection(data) {
417
+ return data.type === "FeatureCollection" && data.features.length === 0;
418
+ }
419
+ function get2DBBox(bbox2) {
420
+ if (bbox2.length === 4) return bbox2;
421
+ return [bbox2[0], bbox2[1], bbox2[3], bbox2[4]];
422
+ }
423
+ function sortEntries(entries) {
424
+ return [...entries].sort((a, b) => {
425
+ if (a.name === VERSION_FILE) return -1;
426
+ if (b.name === VERSION_FILE) return 1;
427
+ if (a.name === STYLE_FILE) return -1;
428
+ if (b.name === STYLE_FILE) return 1;
429
+ const foldersA = a.name.split("/");
430
+ const foldersB = b.name.split("/");
431
+ const aIsFirst = foldersA[0] === FONTS_FOLDER && foldersA[2] === "0-255.pbf.gz";
432
+ const bIsFirst = foldersB[0] === FONTS_FOLDER && foldersB[2] === "0-255.pbf.gz";
433
+ if (aIsFirst && bIsFirst)
434
+ return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
435
+ if (aIsFirst) return -1;
436
+ if (bIsFirst) return 1;
437
+ if (foldersA[0] === SOURCES_FOLDER && foldersB[0] !== SOURCES_FOLDER)
438
+ return -1;
439
+ if (foldersB[0] === SOURCES_FOLDER && foldersA[0] !== SOURCES_FOLDER)
440
+ return 1;
441
+ if (foldersA[0] === SOURCES_FOLDER && foldersB[0] === SOURCES_FOLDER) {
442
+ const zoomA = +foldersA[2];
443
+ const zoomB = +foldersB[2];
444
+ return zoomA - zoomB;
445
+ }
446
+ return 0;
447
+ });
448
+ }
449
+ export {
450
+ SUPPORTED_SOURCE_TYPES,
451
+ Writer
452
+ };
package/package.json ADDED
@@ -0,0 +1,161 @@
1
+ {
2
+ "name": "styled-map-package-api",
3
+ "version": "5.0.0-pre.0",
4
+ "description": "JavaScript API for reading, writing, and serving Styled Map Package (.smp) files",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "./reader": {
21
+ "import": {
22
+ "types": "./dist/reader.d.ts",
23
+ "default": "./dist/reader.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/reader.d.cts",
27
+ "default": "./dist/reader.cjs"
28
+ }
29
+ },
30
+ "./writer": {
31
+ "import": {
32
+ "types": "./dist/writer.d.ts",
33
+ "default": "./dist/writer.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/writer.d.cts",
37
+ "default": "./dist/writer.cjs"
38
+ }
39
+ },
40
+ "./server": {
41
+ "import": {
42
+ "types": "./dist/server.d.ts",
43
+ "default": "./dist/server.js"
44
+ },
45
+ "require": {
46
+ "types": "./dist/server.d.cts",
47
+ "default": "./dist/server.cjs"
48
+ }
49
+ },
50
+ "./style-downloader": {
51
+ "import": {
52
+ "types": "./dist/style-downloader.d.ts",
53
+ "default": "./dist/style-downloader.js"
54
+ },
55
+ "require": {
56
+ "types": "./dist/style-downloader.d.cts",
57
+ "default": "./dist/style-downloader.cjs"
58
+ }
59
+ },
60
+ "./tile-downloader": {
61
+ "import": {
62
+ "types": "./dist/tile-downloader.d.ts",
63
+ "default": "./dist/tile-downloader.js"
64
+ },
65
+ "require": {
66
+ "types": "./dist/tile-downloader.d.cts",
67
+ "default": "./dist/tile-downloader.cjs"
68
+ }
69
+ },
70
+ "./download": {
71
+ "import": {
72
+ "types": "./dist/download.d.ts",
73
+ "default": "./dist/download.js"
74
+ },
75
+ "require": {
76
+ "types": "./dist/download.d.cts",
77
+ "default": "./dist/download.cjs"
78
+ }
79
+ },
80
+ "./from-mbtiles": {
81
+ "import": {
82
+ "types": "./dist/from-mbtiles.d.ts",
83
+ "default": "./dist/from-mbtiles.js"
84
+ },
85
+ "require": {
86
+ "types": "./dist/from-mbtiles.d.cts",
87
+ "default": "./dist/from-mbtiles.cjs"
88
+ }
89
+ },
90
+ "./utils/mapbox": {
91
+ "import": {
92
+ "types": "./dist/utils/mapbox.d.ts",
93
+ "default": "./dist/utils/mapbox.js"
94
+ },
95
+ "require": {
96
+ "types": "./dist/utils/mapbox.d.cts",
97
+ "default": "./dist/utils/mapbox.cjs"
98
+ }
99
+ },
100
+ "./package.json": "./package.json"
101
+ },
102
+ "files": [
103
+ "dist"
104
+ ],
105
+ "scripts": {
106
+ "test": "npm run build && npm run types && vitest run",
107
+ "test:watch": "vitest",
108
+ "test:coverage": "vitest run --coverage",
109
+ "build": "tsup",
110
+ "types": "tsc",
111
+ "bench": "vitest bench --project node",
112
+ "prepack": "npm run build"
113
+ },
114
+ "keywords": [],
115
+ "license": "MIT",
116
+ "dependencies": {
117
+ "@gmaclennan/zip-reader": "^1.0.0-pre.2",
118
+ "@mapbox/sphericalmercator": "^1.2.0",
119
+ "@maplibre/maplibre-gl-style-spec": "^20.3.1",
120
+ "@placemarkio/check-geojson": "^0.1.12",
121
+ "@turf/bbox": "^7.2.0",
122
+ "@turf/helpers": "^7.2.0",
123
+ "filter-obj": "^6.1.0",
124
+ "itty-router": "^5.0.22",
125
+ "ky": "^1.7.5",
126
+ "map-obj": "^5.0.2",
127
+ "mbtiles-reader": "^1.0.0",
128
+ "p-limit": "^6.2.0",
129
+ "readable-stream": "^4.7.0",
130
+ "yocto-queue": "^1.1.1",
131
+ "zip-writer": "^2.2.0"
132
+ },
133
+ "devDependencies": {
134
+ "@commander-js/extra-typings": "^12.1.0",
135
+ "@types/geojson": "^7946.0.16",
136
+ "@types/http-errors": "^2.0.4",
137
+ "@types/mapbox__sphericalmercator": "^1.2.3",
138
+ "@types/node": "^18.19.130",
139
+ "@types/readable-stream": "^4.0.18",
140
+ "@vitest/browser": "^3.2.4",
141
+ "@vitest/coverage-v8": "^3.2.4",
142
+ "@whatwg-node/server": "^0.10.17",
143
+ "esbuild-fix-imports-plugin": "^1.0.20",
144
+ "execa": "^9.4.0",
145
+ "fast-png": "^6.3.0",
146
+ "pixel-stream": "^1.0.3",
147
+ "playwright": "^1.50.1",
148
+ "sharp": "^0.33.5",
149
+ "tempy": "^3.1.0",
150
+ "tsup": "^8.4.0",
151
+ "type-fest": "^4.35.0",
152
+ "typescript": "^5.9.3",
153
+ "vite": "^6.4.1",
154
+ "vitest": "^3.2.4"
155
+ },
156
+ "repository": {
157
+ "type": "git",
158
+ "url": "git+https://github.com/digidem/styled-map-package.git",
159
+ "directory": "packages/api"
160
+ }
161
+ }