styled-map-package 1.0.1 → 2.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.
- package/bin/smp-view.js +1 -0
- package/dist/download.d.ts +49 -0
- package/dist/index.d.ts +9 -0
- package/dist/reader-watch.d.ts +13 -0
- package/dist/reader.d.ts +51 -0
- package/dist/reporters.d.ts +7 -0
- package/dist/server.d.ts +21 -0
- package/dist/style-downloader.d.ts +110 -0
- package/dist/tile-downloader.d.ts +72 -0
- package/dist/types.d.ts +64 -0
- package/dist/utils/errors.d.ts +16 -0
- package/dist/utils/fetch.d.ts +54 -0
- package/dist/utils/file-formats.d.ts +25 -0
- package/dist/utils/geo.d.ts +44 -0
- package/dist/utils/mapbox.d.ts +40 -0
- package/dist/utils/misc.d.ts +20 -0
- package/dist/utils/streams.d.ts +69 -0
- package/dist/utils/style.d.ts +59 -0
- package/dist/utils/templates.d.ts +68 -0
- package/dist/writer.d.ts +130 -0
- package/lib/index.js +4 -0
- package/lib/reader-watch.js +133 -0
- package/lib/reader.js +18 -3
- package/lib/server.js +44 -27
- package/lib/utils/errors.js +24 -0
- package/lib/utils/streams.js +4 -1
- package/map-viewer/index.html +1 -1
- package/package.json +51 -10
- package/.github/workflows/node.yml +0 -30
- package/.github/workflows/release.yml +0 -47
- package/.husky/pre-commit +0 -1
- package/.nvmrc +0 -1
- package/eslint.config.js +0 -17
- package/test/download-write-read.js +0 -43
- package/test/fixtures/invalid-styles/empty.json +0 -1
- package/test/fixtures/invalid-styles/missing-source.json +0 -10
- package/test/fixtures/invalid-styles/no-layers.json +0 -4
- package/test/fixtures/invalid-styles/no-sources.json +0 -4
- package/test/fixtures/invalid-styles/null.json +0 -1
- package/test/fixtures/invalid-styles/unsupported-version.json +0 -5
- package/test/fixtures/valid-styles/external-geojson.input.json +0 -66
- package/test/fixtures/valid-styles/external-geojson.output.json +0 -93
- package/test/fixtures/valid-styles/inline-geojson.input.json +0 -421
- package/test/fixtures/valid-styles/inline-geojson.output.json +0 -1573
- package/test/fixtures/valid-styles/maplibre-demotiles.input.json +0 -831
- package/test/fixtures/valid-styles/maplibre-unlabelled.input.json +0 -496
- package/test/fixtures/valid-styles/maplibre-unlabelled.output.json +0 -1573
- package/test/fixtures/valid-styles/minimal-labelled.input.json +0 -37
- package/test/fixtures/valid-styles/minimal-labelled.output.json +0 -72
- package/test/fixtures/valid-styles/minimal-sprites.input.json +0 -37
- package/test/fixtures/valid-styles/minimal-sprites.output.json +0 -58
- package/test/fixtures/valid-styles/minimal.input.json +0 -54
- package/test/fixtures/valid-styles/minimal.output.json +0 -92
- package/test/fixtures/valid-styles/multiple-sprites.input.json +0 -46
- package/test/fixtures/valid-styles/multiple-sprites.output.json +0 -128
- package/test/fixtures/valid-styles/raster-sources.input.json +0 -33
- package/test/fixtures/valid-styles/raster-sources.output.json +0 -69
- package/test/utils/assert-bbox-equal.js +0 -19
- package/test/utils/digest-stream.js +0 -36
- package/test/utils/image-streams.js +0 -30
- package/test/utils/reader-helper.js +0 -72
- package/test/write-read.js +0 -620
- package/tsconfig.json +0 -18
- package/types/buffer-peek-stream.d.ts +0 -12
package/bin/smp-view.js
CHANGED
|
@@ -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
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { default as Reader } from "./reader.js";
|
|
2
|
+
export { default as ReaderWatch } from "./reader-watch.js";
|
|
3
|
+
export { default as Writer } from "./writer.js";
|
|
4
|
+
export { default as Server } from "./server.js";
|
|
5
|
+
export { default as StyleDownloader } from "./style-downloader.js";
|
|
6
|
+
export { downloadTiles } from "./tile-downloader.js";
|
|
7
|
+
export { default as download } from "./download.js";
|
|
8
|
+
export type SMPSource = import("./types.js").SMPSource;
|
|
9
|
+
export type SMPStyle = import("./types.js").SMPStyle;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** @implements {Pick<Reader, keyof Reader>} */
|
|
2
|
+
export default class ReaderWatch implements Pick<Reader, keyof Reader> {
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} filepath
|
|
5
|
+
*/
|
|
6
|
+
constructor(filepath: string);
|
|
7
|
+
opened(): Promise<void>;
|
|
8
|
+
getStyle(baseUrl?: string | null | undefined): Promise<import("./types.js").SMPStyle>;
|
|
9
|
+
getResource(path: string): Promise<Resource>;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
#private;
|
|
12
|
+
}
|
|
13
|
+
import Reader from './reader.js';
|
package/dist/reader.d.ts
ADDED
|
@@ -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';
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
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 PluginOptionsFilepath = {
|
|
3
|
+
/**
|
|
4
|
+
* Path to styled map package (`.smp`) file
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Path to styled map package (`.smp`) file
|
|
8
|
+
*/
|
|
9
|
+
filepath: string;
|
|
10
|
+
};
|
|
11
|
+
export type PluginOptionsReader = {
|
|
12
|
+
/**
|
|
13
|
+
* SMP Reader interface (also supports ReaderWatch)
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* SMP Reader interface (also supports ReaderWatch)
|
|
17
|
+
*/
|
|
18
|
+
reader: Pick<Reader, keyof Reader>;
|
|
19
|
+
};
|
|
20
|
+
export type PluginOptions = PluginOptionsFilepath | PluginOptionsReader;
|
|
21
|
+
import Reader from './reader.js';
|
|
@@ -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';
|
package/dist/types.d.ts
ADDED
|
@@ -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,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true if the error if because a file is not found. On Windows, some
|
|
3
|
+
* operations like fs.watch() throw an EPERM error rather than ENOENT.
|
|
4
|
+
*
|
|
5
|
+
* @param {unknown} error
|
|
6
|
+
* @returns {error is Error & { code: 'ENOENT' | 'EPERM' }}
|
|
7
|
+
*/
|
|
8
|
+
export function isFileNotThereError(error: unknown): error is Error & {
|
|
9
|
+
code: "ENOENT" | "EPERM";
|
|
10
|
+
};
|
|
11
|
+
export class ENOENT extends Error {
|
|
12
|
+
/** @param {string} path */
|
|
13
|
+
constructor(path: string);
|
|
14
|
+
code: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}
|
|
@@ -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);
|