styled-map-package 1.0.1 → 1.1.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 (62) hide show
  1. package/bin/smp-view.js +1 -0
  2. package/dist/download.d.ts +49 -0
  3. package/dist/index.d.ts +8 -0
  4. package/dist/reader.d.ts +51 -0
  5. package/dist/reporters.d.ts +7 -0
  6. package/dist/server.d.ts +12 -0
  7. package/dist/style-downloader.d.ts +110 -0
  8. package/dist/tile-downloader.d.ts +72 -0
  9. package/dist/types.d.ts +64 -0
  10. package/dist/utils/errors.d.ts +6 -0
  11. package/dist/utils/fetch.d.ts +54 -0
  12. package/dist/utils/file-formats.d.ts +25 -0
  13. package/dist/utils/geo.d.ts +44 -0
  14. package/dist/utils/mapbox.d.ts +40 -0
  15. package/dist/utils/misc.d.ts +20 -0
  16. package/dist/utils/streams.d.ts +69 -0
  17. package/dist/utils/style.d.ts +59 -0
  18. package/dist/utils/templates.d.ts +68 -0
  19. package/dist/writer.d.ts +130 -0
  20. package/lib/index.js +3 -0
  21. package/lib/reader.js +18 -3
  22. package/lib/server.js +75 -23
  23. package/lib/utils/errors.js +9 -0
  24. package/lib/utils/streams.js +4 -1
  25. package/map-viewer/index.html +1 -1
  26. package/package.json +47 -10
  27. package/.github/workflows/node.yml +0 -30
  28. package/.github/workflows/release.yml +0 -47
  29. package/.husky/pre-commit +0 -1
  30. package/.nvmrc +0 -1
  31. package/eslint.config.js +0 -17
  32. package/test/download-write-read.js +0 -43
  33. package/test/fixtures/invalid-styles/empty.json +0 -1
  34. package/test/fixtures/invalid-styles/missing-source.json +0 -10
  35. package/test/fixtures/invalid-styles/no-layers.json +0 -4
  36. package/test/fixtures/invalid-styles/no-sources.json +0 -4
  37. package/test/fixtures/invalid-styles/null.json +0 -1
  38. package/test/fixtures/invalid-styles/unsupported-version.json +0 -5
  39. package/test/fixtures/valid-styles/external-geojson.input.json +0 -66
  40. package/test/fixtures/valid-styles/external-geojson.output.json +0 -93
  41. package/test/fixtures/valid-styles/inline-geojson.input.json +0 -421
  42. package/test/fixtures/valid-styles/inline-geojson.output.json +0 -1573
  43. package/test/fixtures/valid-styles/maplibre-demotiles.input.json +0 -831
  44. package/test/fixtures/valid-styles/maplibre-unlabelled.input.json +0 -496
  45. package/test/fixtures/valid-styles/maplibre-unlabelled.output.json +0 -1573
  46. package/test/fixtures/valid-styles/minimal-labelled.input.json +0 -37
  47. package/test/fixtures/valid-styles/minimal-labelled.output.json +0 -72
  48. package/test/fixtures/valid-styles/minimal-sprites.input.json +0 -37
  49. package/test/fixtures/valid-styles/minimal-sprites.output.json +0 -58
  50. package/test/fixtures/valid-styles/minimal.input.json +0 -54
  51. package/test/fixtures/valid-styles/minimal.output.json +0 -92
  52. package/test/fixtures/valid-styles/multiple-sprites.input.json +0 -46
  53. package/test/fixtures/valid-styles/multiple-sprites.output.json +0 -128
  54. package/test/fixtures/valid-styles/raster-sources.input.json +0 -33
  55. package/test/fixtures/valid-styles/raster-sources.output.json +0 -69
  56. package/test/utils/assert-bbox-equal.js +0 -19
  57. package/test/utils/digest-stream.js +0 -36
  58. package/test/utils/image-streams.js +0 -30
  59. package/test/utils/reader-helper.js +0 -72
  60. package/test/write-read.js +0 -620
  61. package/tsconfig.json +0 -18
  62. package/types/buffer-peek-stream.d.ts +0 -12
package/bin/smp-view.js CHANGED
@@ -47,6 +47,7 @@ function serve({ port = 3000, filepath }) {
47
47
 
48
48
  server.register(smpServer, {
49
49
  filepath: path.relative(process.cwd(), filepath),
50
+ prefix: '/map',
50
51
  })
51
52
  return server.listen({ port })
52
53
  }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @typedef {object} DownloadProgress
3
+ * @property {import('./tile-downloader.js').TileDownloadStats & { done: boolean }} tiles
4
+ * @property {{ done: boolean }} style
5
+ * @property {{ downloaded: number, done: boolean }} sprites
6
+ * @property {import('./style-downloader.js').GlyphDownloadStats & { done: boolean }} glyphs
7
+ * @property {{ totalBytes: number, done: boolean }} output
8
+ * @property {number} elapsedMs
9
+ */
10
+ /**
11
+ * Download a map style and its resources for a given bounding box and max zoom
12
+ * level. Returns a readable stream of a "styled map package", a zip file
13
+ * containing all the resources needed to serve the style offline.
14
+ *
15
+ * @param {object} opts
16
+ * @param {import("./utils/geo.js").BBox} opts.bbox Bounding box to download tiles for
17
+ * @param {number} opts.maxzoom Max zoom level to download tiles for
18
+ * @param {string} opts.styleUrl URL of the style to download
19
+ * @param { (progress: DownloadProgress) => void } [opts.onprogress] Optional callback for reporting progress
20
+ * @param {string} [opts.accessToken]
21
+ * @returns {import('./types.js').DownloadStream} Readable stream of the output styled map file
22
+ */
23
+ export default function download({ bbox, maxzoom, styleUrl, onprogress, accessToken, }: {
24
+ bbox: import("./utils/geo.js").BBox;
25
+ maxzoom: number;
26
+ styleUrl: string;
27
+ onprogress?: ((progress: DownloadProgress) => void) | undefined;
28
+ accessToken?: string | undefined;
29
+ }): import("./types.js").DownloadStream;
30
+ export type DownloadProgress = {
31
+ tiles: import("./tile-downloader.js").TileDownloadStats & {
32
+ done: boolean;
33
+ };
34
+ style: {
35
+ done: boolean;
36
+ };
37
+ sprites: {
38
+ downloaded: number;
39
+ done: boolean;
40
+ };
41
+ glyphs: import("./style-downloader.js").GlyphDownloadStats & {
42
+ done: boolean;
43
+ };
44
+ output: {
45
+ totalBytes: number;
46
+ done: boolean;
47
+ };
48
+ elapsedMs: number;
49
+ };
@@ -0,0 +1,8 @@
1
+ export { default as Reader } from "./reader.js";
2
+ export { default as Writer } from "./writer.js";
3
+ export { default as Server } from "./server.js";
4
+ export { default as StyleDownloader } from "./style-downloader.js";
5
+ export { downloadTiles } from "./tile-downloader.js";
6
+ export { default as download } from "./download.js";
7
+ export type SMPSource = import("./types.js").SMPSource;
8
+ export type SMPStyle = import("./types.js").SMPStyle;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @typedef {object} Resource
3
+ * @property {string} resourceType
4
+ * @property {string} contentType
5
+ * @property {number} contentLength
6
+ * @property {import('stream').Readable} stream
7
+ * @property {'gzip'} [contentEncoding]
8
+ */
9
+ /**
10
+ * A low-level reader for styled map packages. Returns resources in the package
11
+ * as readable streams, for serving over HTTP for example.
12
+ */
13
+ export default class Reader {
14
+ /**
15
+ * @param {string | import('yauzl-promise').ZipFile} filepathOrZip Path to styled map package (`.styledmap`) file, or an instance of yauzl ZipFile
16
+ */
17
+ constructor(filepathOrZip: string | import("yauzl-promise").ZipFile);
18
+ /**
19
+ * Resolves when the styled map package has been opened and the entries have
20
+ * been read. Throws any error that occurred during opening.
21
+ */
22
+ opened(): Promise<void>;
23
+ /**
24
+ * Get the style JSON from the styled map package. The URLs in the style JSON
25
+ * will be transformed to use the provided base URL.
26
+ *
27
+ * @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`
28
+ * @returns {Promise<import('./types.js').SMPStyle>}
29
+ */
30
+ getStyle(baseUrl?: string | null | undefined): Promise<import("./types.js").SMPStyle>;
31
+ /**
32
+ * Get a resource from the styled map package. The path should be relative to
33
+ * the root of the package.
34
+ *
35
+ * @param {string} path
36
+ * @returns {Promise<Resource>}
37
+ */
38
+ getResource(path: string): Promise<Resource>;
39
+ /**
40
+ * Close the styled map package file (should be called after reading the file to avoid memory leaks)
41
+ */
42
+ close(): Promise<void>;
43
+ #private;
44
+ }
45
+ export type Resource = {
46
+ resourceType: string;
47
+ contentType: string;
48
+ contentLength: number;
49
+ stream: import("stream").Readable;
50
+ contentEncoding?: "gzip" | undefined;
51
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A writable stream to reporting download progress to a TTY terminal. Write
3
+ * progress messages to this stream for a pretty-printed progress task-list in
4
+ * the terminal.
5
+ */
6
+ export function ttyReporter(): Writable;
7
+ import { Writable } from 'readable-stream';
@@ -0,0 +1,12 @@
1
+ export default function _default(instance: import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>, opts: PluginOptions, done: (err?: Error) => void): void;
2
+ export type PluginOptions = {
3
+ lazy?: boolean | undefined;
4
+ prefix?: string | undefined;
5
+ /**
6
+ * Path to styled map package (`.smp`) file
7
+ */
8
+ /**
9
+ * Path to styled map package (`.smp`) file
10
+ */
11
+ filepath: string;
12
+ };
@@ -0,0 +1,110 @@
1
+ /** @import { SourceSpecification, StyleSpecification } from '@maplibre/maplibre-gl-style-spec' */
2
+ /** @import { TileInfo, GlyphInfo, GlyphRange } from './writer.js' */
3
+ /** @import { TileDownloadStats } from './tile-downloader.js' */
4
+ /** @import { StyleInlinedSources, InlinedSource } from './types.js'*/
5
+ /** @typedef { import('ky').ResponsePromise & { body: ReadableStream<Uint8Array> } } ResponsePromise */
6
+ /** @import { DownloadResponse } from './utils/fetch.js' */
7
+ /**
8
+ * @typedef {object} GlyphDownloadStats
9
+ * @property {number} total
10
+ * @property {number} downloaded
11
+ * @property {number} totalBytes
12
+ */
13
+ /**
14
+ * Download a style and its resources for offline use. Please check the terms of
15
+ * service of the map provider you are using before downloading any resources.
16
+ */
17
+ export default class StyleDownloader {
18
+ /**
19
+ * @param {string | StyleSpecification} style A url to a style JSON file or a style object
20
+ * @param {object} [opts]
21
+ * @param {number} [opts.concurrency=8]
22
+ * @param {string} [opts.mapboxAccessToken] Downloading a style from Mapbox requires an access token
23
+ */
24
+ constructor(style: string | StyleSpecification, { concurrency, mapboxAccessToken }?: {
25
+ concurrency?: number | undefined;
26
+ mapboxAccessToken?: string | undefined;
27
+ } | undefined);
28
+ /**
29
+ * Number of active downloads.
30
+ */
31
+ get active(): number;
32
+ /**
33
+ * Download the style JSON for this style and inline the sources
34
+ *
35
+ * @returns {Promise<StyleInlinedSources>}
36
+ */
37
+ getStyle(): Promise<StyleInlinedSources>;
38
+ /**
39
+ * Download the sprite PNGs and JSON files for this style. Returns an async
40
+ * generator of json and png readable streams, and the sprite id and pixel
41
+ * ratio. Downloads pixel ratios `1` and `2`.
42
+ *
43
+ * @returns {AsyncGenerator<{ json: import('stream').Readable, png: import('stream').Readable, id: string, pixelRatio: number }>}
44
+ */
45
+ getSprites(): AsyncGenerator<{
46
+ json: import("stream").Readable;
47
+ png: import("stream").Readable;
48
+ id: string;
49
+ pixelRatio: number;
50
+ }>;
51
+ /**
52
+ * Download all the glyphs for the fonts used in this style. When font stacks
53
+ * are used in the style.json (e.g. lists of prefered fonts like with CSS),
54
+ * then the first font in the stack is downloaded. Defaults to downloading all
55
+ * UTF character ranges, which may be overkill for some styles. TODO: add more
56
+ * options here.
57
+ *
58
+ * Returns an async generator of readable streams of glyph data and glyph info
59
+ * objects.
60
+ *
61
+ * @param {object} opts
62
+ * @param {(progress: GlyphDownloadStats) => void} [opts.onprogress]
63
+ * @returns {AsyncGenerator<[import('stream').Readable, GlyphInfo]>}
64
+ */
65
+ getGlyphs({ onprogress }?: {
66
+ onprogress?: ((progress: GlyphDownloadStats) => void) | undefined;
67
+ }): AsyncGenerator<[import("stream").Readable, GlyphInfo]>;
68
+ /**
69
+ * Get all the tiles for this style within the given bounds and zoom range.
70
+ * Returns an async generator of readable streams of tile data and tile info
71
+ * objects.
72
+ *
73
+ * The returned iterator also has a `skipped` property which is an
74
+ * array of tiles which could not be downloaded, and a `stats` property which
75
+ * is an object with the total number of tiles, downloaded tiles, and total
76
+ * bytes downloaded.
77
+ *
78
+ * @param {object} opts
79
+ * @param {import('./utils/geo.js').BBox} opts.bounds
80
+ * @param {number} opts.maxzoom
81
+ * @param {(progress: TileDownloadStats) => void} [opts.onprogress]
82
+ * @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.
83
+ * @returns {AsyncGenerator<[import('stream').Readable, TileInfo]> & { readonly skipped: Array<TileInfo & { error?: Error }>, readonly stats: TileDownloadStats }}
84
+ */
85
+ getTiles({ bounds, maxzoom, onprogress, trackErrors }: {
86
+ bounds: import("./utils/geo.js").BBox;
87
+ maxzoom: number;
88
+ onprogress?: ((progress: TileDownloadStats) => void) | undefined;
89
+ trackErrors?: boolean | undefined;
90
+ }): AsyncGenerator<[import("stream").Readable, TileInfo]> & {
91
+ readonly skipped: Array<TileInfo & {
92
+ error?: Error;
93
+ }>;
94
+ readonly stats: TileDownloadStats;
95
+ };
96
+ #private;
97
+ }
98
+ export type ResponsePromise = import("ky").ResponsePromise & {
99
+ body: ReadableStream<Uint8Array>;
100
+ };
101
+ export type GlyphDownloadStats = {
102
+ total: number;
103
+ downloaded: number;
104
+ totalBytes: number;
105
+ };
106
+ import type { StyleInlinedSources } from './types.js';
107
+ import type { GlyphInfo } from './writer.js';
108
+ import type { TileDownloadStats } from './tile-downloader.js';
109
+ import type { TileInfo } from './writer.js';
110
+ import type { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
@@ -0,0 +1,72 @@
1
+ /** @typedef {Omit<import('./writer.js').TileInfo, 'sourceId'>} TileInfo */
2
+ /**
3
+ * @typedef {object} TileDownloadStats
4
+ * @property {number} total
5
+ * @property {number} downloaded
6
+ * @property {number} skipped
7
+ * @property {number} totalBytes
8
+ */
9
+ /**
10
+ * Download tiles from a list of tile URLs within a bounding box and zoom range.
11
+ * Returns an async generator of tile data as readable streams and tile info objects.
12
+ *
13
+ * @param {object} opts
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`.
15
+ * @param {import('./utils/geo.js').BBox} opts.bounds Bounding box of the area to download
16
+ * @param {number} opts.maxzoom Maximum zoom level to download
17
+ * @param {(progress: TileDownloadStats) => void} [opts.onprogress] Callback to report download progress
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.
19
+ * @param {import('./utils/geo.js').BBox} [opts.sourceBounds=MAX_BOUNDS] Bounding box of source data.
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.
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)
22
+ * @param {number} [opts.concurrency=8] Number of concurrent downloads (ignored if `fetchQueue` is provided)
23
+ * @param {FetchQueue} [opts.fetchQueue=new FetchQueue(concurrency)] Optional fetch queue to use for downloading tiles
24
+ * @param {'xyz' | 'tms'} [opts.scheme='xyz'] Tile scheme to use for tile URLs
25
+ * @returns {AsyncGenerator<[import('stream').Readable, TileInfo]> & { readonly skipped: Array<TileInfo & { error?: Error }>, readonly stats: TileDownloadStats }}
26
+ */
27
+ export function downloadTiles({ tileUrls, bounds, maxzoom, onprogress, trackErrors, sourceBounds, boundsBuffer, minzoom, concurrency, fetchQueue, scheme, }: {
28
+ tileUrls: string[];
29
+ bounds: import("./utils/geo.js").BBox;
30
+ maxzoom: number;
31
+ onprogress?: ((progress: TileDownloadStats) => void) | undefined;
32
+ trackErrors?: boolean | undefined;
33
+ sourceBounds?: import("./utils/geo.js").BBox | undefined;
34
+ boundsBuffer?: boolean | undefined;
35
+ minzoom?: number | undefined;
36
+ concurrency?: number | undefined;
37
+ fetchQueue?: FetchQueue | undefined;
38
+ scheme?: "xyz" | "tms" | undefined;
39
+ }): AsyncGenerator<[import("stream").Readable, TileInfo]> & {
40
+ readonly skipped: Array<TileInfo & {
41
+ error?: Error;
42
+ }>;
43
+ readonly stats: TileDownloadStats;
44
+ };
45
+ /**
46
+ *
47
+ * @param {object} opts
48
+ * @param {import('./utils/geo.js').BBox} [opts.bounds]
49
+ * @param {import('./utils/geo.js').BBox} [opts.sourceBounds]
50
+ * @param {boolean} [opts.boundsBuffer]
51
+ * @param {number} [opts.minzoom]
52
+ * @param {number} opts.maxzoom
53
+ */
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;
57
+ boundsBuffer?: boolean | undefined;
58
+ minzoom?: number | undefined;
59
+ maxzoom: number;
60
+ }): Generator<{
61
+ x: number;
62
+ y: number;
63
+ z: number;
64
+ }, void, unknown>;
65
+ export type TileInfo = Omit<import("./writer.js").TileInfo, "sourceId">;
66
+ export type TileDownloadStats = {
67
+ total: number;
68
+ downloaded: number;
69
+ skipped: number;
70
+ totalBytes: number;
71
+ };
72
+ import { FetchQueue } from './utils/fetch.js';
@@ -0,0 +1,64 @@
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 { Readable } from 'stream';
4
+ import type { SetRequired } from 'type-fest';
5
+ import { SUPPORTED_SOURCE_TYPES } from './writer.js';
6
+ export type InputSource = Extract<SourceSpecification, {
7
+ type: (typeof SUPPORTED_SOURCE_TYPES)[number];
8
+ }>;
9
+ type TransformInlinedSource<T extends SourceSpecification> = T extends GeoJSONSourceSpecification ? OmitUnion<T, 'data'> & {
10
+ data: GeoJSON;
11
+ } : T extends VectorSourceSpecification | RasterSourceSpecification | RasterDEMSourceSpecification ? SetRequired<OmitUnion<T, 'url'>, 'tiles'> : T;
12
+ /**
13
+ * This is a slightly stricter version of SourceSpecification that requires
14
+ * sources to be inlined (e.g. no urls to TileJSON or GeoJSON files).
15
+ */
16
+ export type InlinedSource = TransformInlinedSource<SourceSpecification>;
17
+ type SupportedInlinedSource = Extract<InlinedSource, {
18
+ type: (typeof SUPPORTED_SOURCE_TYPES)[number];
19
+ }>;
20
+ /**
21
+ * This is a slightly stricter version of StyleSpecification that requires
22
+ * sources to be inlined (e.g. no urls to TileJSON or GeoJSON files).
23
+ */
24
+ export type StyleInlinedSources = Omit<StyleSpecification, 'sources'> & {
25
+ sources: {
26
+ [_: string]: InlinedSource;
27
+ };
28
+ };
29
+ export type SMPSource = TransformSMPInputSource<SupportedInlinedSource>;
30
+ /**
31
+ * This is a slightly stricter version of StyleSpecification that is provided in
32
+ * a Styled Map Package. Tile sources must have tile URLs inlined (they cannot
33
+ * refer to a TileJSON url), and they must have bounds, minzoom, and maxzoom.
34
+ * GeoJSON sources must have inlined GeoJSON (not a URL to a GeoJSON file).
35
+ */
36
+ export type SMPStyle = TransformSMPStyle<StyleSpecification>;
37
+ export type TransformSMPInputSource<T extends SupportedInlinedSource> = T extends GeoJSONSourceSpecification ? T & {
38
+ data: {
39
+ bbox: BBox;
40
+ };
41
+ } : T extends RasterSourceSpecification | VectorSourceSpecification ? SetRequired<T, 'bounds' | 'minzoom' | 'maxzoom'> : T;
42
+ type TransformSMPStyle<T extends StyleSpecification> = Omit<T, 'sources'> & {
43
+ metadata: {
44
+ 'smp:bounds': [number, number, number, number];
45
+ 'smp:maxzoom': 0;
46
+ 'smp:sourceFolders': {
47
+ [_: string]: string;
48
+ };
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 interface DownloadStream extends Readable {
59
+ iterator(...args: Parameters<Readable['iterator']>): AsyncIterableIterator<Buffer>;
60
+ [Symbol.asyncIterator](): AsyncIterableIterator<Buffer>;
61
+ }
62
+ export type RequiredUnion<T> = T extends any ? Required<T> : never;
63
+ export type OmitUnion<T, K extends keyof any> = T extends unknown ? Omit<T, K> : never;
64
+ export {};
@@ -0,0 +1,6 @@
1
+ export class ENOENT extends Error {
2
+ /** @param {string} path */
3
+ constructor(path: string);
4
+ code: string;
5
+ path: string;
6
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @typedef {object} DownloadResponse
3
+ * @property {import('stream').Readable} body Node ReadableStream of the response body
4
+ * @property {string | null} mimeType Content mime-type (from http content-type header)
5
+ * @property {number | null} contentLength Content length in bytes (from http content-length header)
6
+ */
7
+ /**
8
+ * A wrapper for fetch that limits the number of concurrent downloads.
9
+ */
10
+ export class FetchQueue {
11
+ /** @param {number} concurrency */
12
+ constructor(concurrency: number);
13
+ get activeCount(): number;
14
+ /**
15
+ * Fetch a URL, limiting the number of concurrent downloads. Resolves with a
16
+ * `DownloadResponse`, which is a parsed from the Fetch `Response` objects,
17
+ * with `body` as a Node readable stream, and the MIME type and content length
18
+ * of the response.
19
+ *
20
+ * NB: The response body stream must be consumed to the end, otherwise the
21
+ * queue will never be emptied.
22
+ *
23
+ * @param {string} url
24
+ * @param {{ onprogress?: import('./streams.js').ProgressCallback }} opts
25
+ * @returns {Promise<DownloadResponse>}
26
+ */
27
+ fetch(url: string, { onprogress }?: {
28
+ onprogress?: import("./streams.js").ProgressCallback;
29
+ }): Promise<DownloadResponse>;
30
+ #private;
31
+ }
32
+ export type DownloadResponse = {
33
+ /**
34
+ * Node ReadableStream of the response body
35
+ */
36
+ /**
37
+ * Node ReadableStream of the response body
38
+ */
39
+ body: import("stream").Readable;
40
+ /**
41
+ * Content mime-type (from http content-type header)
42
+ */
43
+ /**
44
+ * Content mime-type (from http content-type header)
45
+ */
46
+ mimeType: string | null;
47
+ /**
48
+ * Content length in bytes (from http content-length header)
49
+ */
50
+ /**
51
+ * Content length in bytes (from http content-length header)
52
+ */
53
+ contentLength: number | null;
54
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * For a given buffer, determine the tile format based on the magic bytes.
3
+ * Will throw for unknown file types.
4
+ * Smaller and faster version of magic-bytes.js due to the limited use case.
5
+ *
6
+ * @param {Buffer | Uint8Array} buf
7
+ * @returns {import("../writer.js").TileFormat}
8
+ */
9
+ export function getTileFormatFromBuffer(buf: Buffer | Uint8Array): import("../writer.js").TileFormat;
10
+ /**
11
+ * Determine the tile format from either a readable stream, buffer or Uint8Array
12
+ * from the magic bytes at the start of the file. Used if data is served without
13
+ * a content-type header.
14
+ *
15
+ * @param {import('stream').Readable} tileData
16
+ * @returns {Promise<[import("../writer.js").TileFormat, import('stream').Readable]>}
17
+ */
18
+ export function getTileFormatFromStream(tileData: import("stream").Readable): Promise<[import("../writer.js").TileFormat, import("stream").Readable]>;
19
+ /**
20
+ * Get the tile format from a MIME type. Throws for unsupported types.
21
+ *
22
+ * @param {string} mimeType
23
+ * @returns {import("../writer.js").TileFormat}
24
+ */
25
+ export function getFormatFromMimeType(mimeType: string): import("../writer.js").TileFormat;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @typedef {[number, number, number, number]} BBox
3
+ */
4
+ /**
5
+ * Return the bounding box for the given tile.
6
+ *
7
+ * @param {{ x: number, y: number, z: number }} tile
8
+ * @returns {BBox} Bounding Box [w, s, e, n]
9
+ */
10
+ export function tileToBBox({ x, y, z }: {
11
+ x: number;
12
+ y: number;
13
+ z: number;
14
+ }): BBox;
15
+ /**
16
+ * @param {{ x: number, y: number, z: number }} tile
17
+ */
18
+ export function getQuadkey({ x, y, z }: {
19
+ x: number;
20
+ y: number;
21
+ z: number;
22
+ }): string;
23
+ /**
24
+ * From an array of tile URL templates, get the URL for the given tile.
25
+ *
26
+ * @param {string[]} urls
27
+ * @param {{ x: number, y: number, z: number, scheme?: 'xyz' | 'tms' }} opts
28
+ */
29
+ export function getTileUrl(urls: string[], { x, y, z, scheme }: {
30
+ x: number;
31
+ y: number;
32
+ z: number;
33
+ scheme?: "xyz" | "tms";
34
+ }): string;
35
+ /**
36
+ * Returns a bbox that is the smallest bounding box that contains all the input bboxes.
37
+ *
38
+ * @param {[BBox, ...BBox[]]} bboxes
39
+ * @returns {BBox} Bounding Box [w, s, e, n]
40
+ */
41
+ export function unionBBox(bboxes: [BBox, ...BBox[]]): BBox;
42
+ /** Spherical Mercator max bounds, rounded to 6 decimal places */
43
+ export const MAX_BOUNDS: BBox;
44
+ export type BBox = [number, number, number, number];
@@ -0,0 +1,40 @@
1
+ /** @param {string} url */
2
+ export function isMapboxURL(url: string): boolean;
3
+ /**
4
+ * @param {string} url
5
+ * @param {string} [accessToken]
6
+ */
7
+ export function normalizeStyleURL(url: string, accessToken?: string | undefined): string;
8
+ /**
9
+ * @param {string} url
10
+ * @param {string} [accessToken]
11
+ */
12
+ export function normalizeGlyphsURL(url: string, accessToken?: string | undefined): string;
13
+ /**
14
+ * @param {string} url
15
+ * @param {string} [accessToken]
16
+ */
17
+ export function normalizeSourceURL(url: string, accessToken?: string | undefined): string;
18
+ /**
19
+ * @param {string} url
20
+ * @param {'' | '@2x'} format
21
+ * @param {'.png' | '.json'} extension
22
+ * @param {string} [accessToken]
23
+ */
24
+ export function normalizeSpriteURL(url: string, format: "" | "@2x", extension: ".png" | ".json", accessToken?: string | undefined): string;
25
+ /**
26
+ * @param {any} tileURL
27
+ * @param {string} sourceURL
28
+ * @param {256 | 512} [tileSize]
29
+ * @param {{ devicePixelRatio?: number; supportsWebp?: boolean; }} [opts]
30
+ */
31
+ export function normalizeTileURL(tileURL: any, sourceURL: string, tileSize?: 256 | 512 | undefined, { devicePixelRatio, supportsWebp }?: {
32
+ devicePixelRatio?: number;
33
+ supportsWebp?: boolean;
34
+ } | undefined): any;
35
+ export type URLObject = {
36
+ protocol: string;
37
+ authority: string;
38
+ path: string;
39
+ params: string[];
40
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Dumb and quick clone an object. Won't keep undefined properties. Types could
3
+ * be tighted so that return type excludes undefined properties, but not really
4
+ * needed.
5
+ *
6
+ * @template T
7
+ * @param {T} obj
8
+ * @returns {T}
9
+ */
10
+ export function clone<T>(obj: T): T;
11
+ export function noop(): void;
12
+ /**
13
+ * Like `Object.hasOwn`, but refines the type of `key`.
14
+ *
15
+ * @template {Record<string, unknown>} T
16
+ * @param {T} obj
17
+ * @param {string} key
18
+ * @returns {key is (keyof T)}
19
+ */
20
+ export function hasOwn<T extends Record<string, unknown>>(obj: T, key: string): key is (keyof T);
@@ -0,0 +1,69 @@
1
+ /** @import { TransformOptions } from 'readable-stream' */
2
+ /**
3
+ * Create a writable stream from an async function. Default concurrecy is 16 -
4
+ * this is the number of parallel functions that will be pending before
5
+ * backpressure is applied on the stream.
6
+ *
7
+ * @template {(...args: any[]) => Promise<void>} T
8
+ * @param {T} fn
9
+ * @returns {import('readable-stream').Writable}
10
+ */
11
+ export function writeStreamFromAsync<T extends (...args: any[]) => Promise<void>>(fn: T, { concurrency }?: {
12
+ concurrency?: number | undefined;
13
+ }): import("readable-stream").Writable;
14
+ /**
15
+ * From https://github.com/nodejs/node/blob/430c0269/lib/internal/webstreams/adapters.js#L509
16
+ *
17
+ * @param {ReadableStream} readableStream
18
+ * @param {{
19
+ * highWaterMark? : number,
20
+ * encoding? : string,
21
+ * objectMode? : boolean,
22
+ * signal? : AbortSignal,
23
+ * }} [options]
24
+ * @returns {import('stream').Readable}
25
+ */
26
+ export function fromWebReadableStream(readableStream: ReadableStream, options?: {
27
+ highWaterMark?: number;
28
+ encoding?: string;
29
+ objectMode?: boolean;
30
+ signal?: AbortSignal;
31
+ } | undefined): import("stream").Readable;
32
+ /**
33
+ * @param {unknown} obj
34
+ * @returns {obj is ReadableStream}
35
+ */
36
+ export function isWebReadableStream(obj: unknown): obj is ReadableStream;
37
+ /** @typedef {(opts: { totalBytes: number, chunkBytes: number }) => void} ProgressCallback */
38
+ /** @typedef {TransformOptions & { onprogress?: ProgressCallback }} ProgressStreamOptions */
39
+ /**
40
+ * Passthrough stream that counts the bytes passing through it. Pass an optional
41
+ * `onprogress` callback that will be called with the accumulated total byte
42
+ * count and the chunk byte count after each chunk.
43
+ * @extends {Transform}
44
+ */
45
+ export class ProgressStream extends Transform {
46
+ /**
47
+ * @param {ProgressStreamOptions} [opts]
48
+ */
49
+ constructor({ onprogress, ...opts }?: ProgressStreamOptions | undefined);
50
+ /** Total bytes that have passed through this stream */
51
+ get byteLength(): number;
52
+ /**
53
+ * @override
54
+ * @param {Buffer | Uint8Array} chunk
55
+ * @param {Parameters<Transform['_transform']>[1]} encoding
56
+ * @param {Parameters<Transform['_transform']>[2]} callback
57
+ */
58
+ override _transform(chunk: Buffer | Uint8Array, encoding: Parameters<Transform["_transform"]>[1], callback: Parameters<Transform["_transform"]>[2]): void;
59
+ #private;
60
+ }
61
+ export type ProgressCallback = (opts: {
62
+ totalBytes: number;
63
+ chunkBytes: number;
64
+ }) => void;
65
+ export type ProgressStreamOptions = TransformOptions & {
66
+ onprogress?: ProgressCallback;
67
+ };
68
+ import { Transform } from 'readable-stream';
69
+ import type { TransformOptions } from 'readable-stream';