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.
- package/bin/smp-download.js +3 -3
- package/bin/smp-mbtiles.js +1 -1
- package/bin/smp-view.js +15 -4
- package/dist/download.cjs +101 -0
- package/dist/download.d.cts +65 -0
- package/dist/{lib/download.d.ts → download.d.ts} +22 -6
- package/dist/download.js +77 -0
- package/dist/from-mbtiles.cjs +91 -0
- package/dist/from-mbtiles.d.cts +17 -0
- package/dist/from-mbtiles.d.ts +17 -0
- package/dist/from-mbtiles.js +57 -0
- package/dist/index.cjs +49 -0
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +18 -0
- package/dist/reader-watch.cjs +135 -0
- package/dist/reader-watch.d.cts +24 -0
- package/dist/reader-watch.d.ts +24 -0
- package/dist/reader-watch.js +101 -0
- package/dist/reader.cjs +167 -0
- package/dist/reader.d.cts +62 -0
- package/dist/{lib/reader.d.ts → reader.d.ts} +16 -5
- package/dist/reader.js +138 -0
- package/dist/reporters.cjs +122 -0
- package/dist/reporters.d.cts +10 -0
- package/dist/{lib/reporters.d.ts → reporters.d.ts} +5 -2
- package/dist/reporters.js +88 -0
- package/dist/server.cjs +79 -0
- package/dist/server.d.cts +48 -0
- package/dist/server.d.ts +48 -0
- package/dist/server.js +55 -0
- package/dist/style-downloader.cjs +312 -0
- package/dist/style-downloader.d.cts +120 -0
- package/dist/{lib/style-downloader.d.ts → style-downloader.d.ts} +23 -13
- package/dist/style-downloader.js +288 -0
- package/dist/tile-downloader.cjs +158 -0
- package/dist/tile-downloader.d.cts +84 -0
- package/dist/{lib/tile-downloader.d.ts → tile-downloader.d.ts} +22 -10
- package/dist/tile-downloader.js +126 -0
- package/dist/{lib/writer.d.ts → types-B4Xn1F9K.d.cts} +74 -14
- package/dist/types-B4Xn1F9K.d.ts +189 -0
- package/dist/utils/errors.cjs +41 -0
- package/dist/utils/errors.d.cts +18 -0
- package/dist/{lib/utils → utils}/errors.d.ts +4 -2
- package/dist/utils/errors.js +16 -0
- package/dist/utils/fetch.cjs +96 -0
- package/dist/utils/fetch.d.cts +51 -0
- package/dist/{lib/utils → utils}/fetch.d.ts +10 -4
- package/dist/utils/fetch.js +62 -0
- package/dist/utils/file-formats.cjs +98 -0
- package/dist/utils/file-formats.d.cts +35 -0
- package/dist/{lib/utils → utils}/file-formats.d.ts +13 -3
- package/dist/utils/file-formats.js +62 -0
- package/dist/utils/geo.cjs +84 -0
- package/dist/utils/geo.d.cts +46 -0
- package/dist/{lib/utils → utils}/geo.d.ts +8 -6
- package/dist/utils/geo.js +56 -0
- package/dist/utils/mapbox.cjs +121 -0
- package/dist/utils/mapbox.d.cts +43 -0
- package/dist/utils/mapbox.d.ts +43 -0
- package/dist/utils/mapbox.js +91 -0
- package/dist/utils/misc.cjs +39 -0
- package/{lib/utils/misc.js → dist/utils/misc.d.cts} +5 -9
- package/dist/{lib/utils → utils}/misc.d.ts +5 -3
- package/dist/utils/misc.js +13 -0
- package/dist/utils/streams.cjs +130 -0
- package/dist/utils/streams.d.cts +73 -0
- package/dist/{lib/utils → utils}/streams.d.ts +14 -10
- package/dist/utils/streams.js +103 -0
- package/dist/utils/style.cjs +126 -0
- package/dist/utils/style.d.cts +69 -0
- package/dist/{lib/utils → utils}/style.d.ts +19 -9
- package/dist/utils/style.js +98 -0
- package/dist/utils/templates.cjs +114 -0
- package/dist/utils/templates.d.cts +78 -0
- package/dist/{lib/utils → utils}/templates.d.ts +24 -14
- package/dist/utils/templates.js +79 -0
- package/dist/writer.cjs +401 -0
- package/dist/writer.d.cts +7 -0
- package/dist/writer.d.ts +7 -0
- package/dist/writer.js +374 -0
- package/package.json +107 -41
- package/dist/lib/from-mbtiles.d.ts +0 -13
- package/dist/lib/index.d.ts +0 -10
- package/dist/lib/reader-watch.d.ts +0 -13
- package/dist/lib/server.d.ts +0 -15
- package/dist/lib/types.d.ts +0 -64
- package/dist/lib/utils/mapbox.d.ts +0 -41
- package/lib/download.js +0 -114
- package/lib/from-mbtiles.js +0 -83
- package/lib/index.js +0 -11
- package/lib/reader-watch.js +0 -133
- package/lib/reader.js +0 -165
- package/lib/reporters.js +0 -92
- package/lib/server.js +0 -81
- package/lib/style-downloader.js +0 -363
- package/lib/tile-downloader.js +0 -188
- package/lib/types.ts +0 -104
- package/lib/utils/errors.js +0 -24
- package/lib/utils/fetch.js +0 -100
- package/lib/utils/file-formats.js +0 -85
- package/lib/utils/geo.js +0 -87
- package/lib/utils/mapbox.js +0 -155
- package/lib/utils/streams.js +0 -165
- package/lib/utils/style.js +0 -174
- package/lib/utils/templates.js +0 -136
- package/lib/writer.js +0 -478
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import SphericalMercator from "@mapbox/sphericalmercator";
|
|
2
|
+
import Queue from "yocto-queue";
|
|
3
|
+
import zlib from "zlib";
|
|
4
|
+
import { FetchQueue } from "./utils/fetch.js";
|
|
5
|
+
import {
|
|
6
|
+
getFormatFromMimeType,
|
|
7
|
+
getTileFormatFromStream
|
|
8
|
+
} from "./utils/file-formats.js";
|
|
9
|
+
import { getTileUrl, MAX_BOUNDS } from "./utils/geo.js";
|
|
10
|
+
import { noop } from "./utils/misc.js";
|
|
11
|
+
function downloadTiles({
|
|
12
|
+
tileUrls,
|
|
13
|
+
bounds,
|
|
14
|
+
maxzoom,
|
|
15
|
+
onprogress = noop,
|
|
16
|
+
trackErrors = false,
|
|
17
|
+
sourceBounds = MAX_BOUNDS,
|
|
18
|
+
boundsBuffer = false,
|
|
19
|
+
minzoom = 0,
|
|
20
|
+
concurrency = 8,
|
|
21
|
+
fetchQueue = new FetchQueue(concurrency),
|
|
22
|
+
scheme = "xyz"
|
|
23
|
+
}) {
|
|
24
|
+
const skipped = [];
|
|
25
|
+
let completed = 0;
|
|
26
|
+
let stats = {
|
|
27
|
+
total: 0,
|
|
28
|
+
downloaded: 0,
|
|
29
|
+
skipped: 0,
|
|
30
|
+
totalBytes: 0
|
|
31
|
+
};
|
|
32
|
+
function onDownloadProgress({ chunkBytes }) {
|
|
33
|
+
stats.totalBytes += chunkBytes;
|
|
34
|
+
onprogress(stats);
|
|
35
|
+
}
|
|
36
|
+
function onDownloadError(error, tileInfo) {
|
|
37
|
+
if (trackErrors) {
|
|
38
|
+
skipped.push({ ...tileInfo, error });
|
|
39
|
+
} else {
|
|
40
|
+
skipped.push(tileInfo);
|
|
41
|
+
}
|
|
42
|
+
onprogress(stats);
|
|
43
|
+
}
|
|
44
|
+
function onDownloadComplete() {
|
|
45
|
+
stats.downloaded = ++completed - skipped.length;
|
|
46
|
+
stats.skipped = skipped.length;
|
|
47
|
+
onprogress(stats);
|
|
48
|
+
}
|
|
49
|
+
const tiles = async function* () {
|
|
50
|
+
const queue = new Queue();
|
|
51
|
+
const tiles2 = tileIterator({
|
|
52
|
+
bounds,
|
|
53
|
+
minzoom,
|
|
54
|
+
maxzoom,
|
|
55
|
+
sourceBounds,
|
|
56
|
+
boundsBuffer
|
|
57
|
+
});
|
|
58
|
+
for (const { x, y, z } of tiles2) {
|
|
59
|
+
const tileURL = getTileUrl(tileUrls, { x, y, z, scheme });
|
|
60
|
+
const tileInfo = { z, x, y };
|
|
61
|
+
const result = fetchQueue.fetch(tileURL, { onprogress: onDownloadProgress }).catch((err) => onDownloadError(err, tileInfo));
|
|
62
|
+
queue.enqueue([result, tileInfo]);
|
|
63
|
+
}
|
|
64
|
+
stats.total = queue.size;
|
|
65
|
+
if (onprogress) onprogress(stats);
|
|
66
|
+
for (const [result, tileInfo] of queue) {
|
|
67
|
+
const downloadResponse = await result.catch(noop);
|
|
68
|
+
if (!downloadResponse) continue;
|
|
69
|
+
let { body, mimeType } = downloadResponse;
|
|
70
|
+
body.on("end", onDownloadComplete);
|
|
71
|
+
body.on("error", (err) => onDownloadError(err, tileInfo));
|
|
72
|
+
let format;
|
|
73
|
+
if (mimeType) {
|
|
74
|
+
format = getFormatFromMimeType(mimeType);
|
|
75
|
+
} else {
|
|
76
|
+
;
|
|
77
|
+
[format, body] = await getTileFormatFromStream(body);
|
|
78
|
+
}
|
|
79
|
+
let stream = body;
|
|
80
|
+
if (format === "mvt") {
|
|
81
|
+
const gzipStream = zlib.createGzip();
|
|
82
|
+
stream = body.pipe(gzipStream);
|
|
83
|
+
stream.on("error", (err) => gzipStream.destroy(err));
|
|
84
|
+
}
|
|
85
|
+
yield [stream, { ...tileInfo, format }];
|
|
86
|
+
}
|
|
87
|
+
}();
|
|
88
|
+
Object.defineProperty(tiles, "skipped", {
|
|
89
|
+
get() {
|
|
90
|
+
return skipped;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
Object.defineProperty(tiles, "stats", {
|
|
94
|
+
get() {
|
|
95
|
+
return stats;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return tiles;
|
|
99
|
+
}
|
|
100
|
+
function* tileIterator({
|
|
101
|
+
bounds = [...MAX_BOUNDS],
|
|
102
|
+
minzoom = 0,
|
|
103
|
+
maxzoom,
|
|
104
|
+
sourceBounds,
|
|
105
|
+
boundsBuffer = false
|
|
106
|
+
}) {
|
|
107
|
+
const sm = new SphericalMercator({ size: 256 });
|
|
108
|
+
for (let z = minzoom; z <= maxzoom; z++) {
|
|
109
|
+
let { minX, minY, maxX, maxY } = sm.xyz([...bounds], z);
|
|
110
|
+
let sourceXYBounds = sourceBounds ? sm.xyz([...sourceBounds], z) : { minX, minY, maxX, maxY };
|
|
111
|
+
const buffer = boundsBuffer ? 1 : 0;
|
|
112
|
+
minX = Math.max(0, minX - buffer, sourceXYBounds.minX);
|
|
113
|
+
minY = Math.max(0, minY - buffer, sourceXYBounds.minY);
|
|
114
|
+
maxX = Math.min(Math.pow(2, z) - 1, maxX + buffer, sourceXYBounds.maxX);
|
|
115
|
+
maxY = Math.min(Math.pow(2, z) - 1, maxY + buffer, sourceXYBounds.maxY);
|
|
116
|
+
for (let x = minX; x <= maxX; x++) {
|
|
117
|
+
for (let y = minY; y <= maxY; y++) {
|
|
118
|
+
yield { x, y, z };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export {
|
|
124
|
+
downloadTiles,
|
|
125
|
+
tileIterator
|
|
126
|
+
};
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import { SourceSpecification, GeoJSONSourceSpecification, VectorSourceSpecification, RasterSourceSpecification, RasterDEMSourceSpecification, StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
|
|
2
|
+
import { GeoJSON, BBox } from 'geojson';
|
|
3
|
+
import * as stream from 'stream';
|
|
4
|
+
import { Readable } from 'stream';
|
|
5
|
+
import { SetRequired } from 'type-fest';
|
|
6
|
+
import * as readable_stream from 'readable-stream';
|
|
7
|
+
import { EventEmitter } from 'events';
|
|
8
|
+
|
|
1
9
|
/** @typedef {string | Buffer | Uint8Array | import('stream').Readable } Source */
|
|
2
10
|
/** @typedef {string | Buffer | import('stream').Readable} SourceInternal */
|
|
3
11
|
/** @typedef {`${number}-${number}`} GlyphRange */
|
|
@@ -23,14 +31,14 @@
|
|
|
23
31
|
*/
|
|
24
32
|
/** @import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec' */
|
|
25
33
|
/** @import { InputSource, SMPSource } from './types.js' */
|
|
26
|
-
|
|
34
|
+
declare const SUPPORTED_SOURCE_TYPES: readonly ["raster", "vector", "geojson"];
|
|
27
35
|
/**
|
|
28
36
|
* Write a styled map package to a stream. Stream `writer.outputStream` to a
|
|
29
37
|
* destination, e.g. `fs.createWriteStream('my-map.styledmap')`. You must call
|
|
30
38
|
* `witer.finish()` and then wait for your writable stream to `finish` before
|
|
31
39
|
* using the output.
|
|
32
40
|
*/
|
|
33
|
-
|
|
41
|
+
declare class Writer extends EventEmitter<[never]> {
|
|
34
42
|
static SUPPORTED_SOURCE_TYPES: readonly ["raster", "vector", "geojson"];
|
|
35
43
|
/**
|
|
36
44
|
* @param {any} style A v7 or v8 MapLibre style. v7 styles will be migrated to
|
|
@@ -45,7 +53,7 @@ export default class Writer extends EventEmitter<[never]> {
|
|
|
45
53
|
/**
|
|
46
54
|
* @returns {import('stream').Readable} Readable stream of the styled map package
|
|
47
55
|
*/
|
|
48
|
-
get outputStream():
|
|
56
|
+
get outputStream(): stream.Readable;
|
|
49
57
|
/**
|
|
50
58
|
* Add a tile to the styled map package
|
|
51
59
|
*
|
|
@@ -63,7 +71,7 @@ export default class Writer extends EventEmitter<[never]> {
|
|
|
63
71
|
*/
|
|
64
72
|
createTileWriteStream({ concurrency }?: {
|
|
65
73
|
concurrency?: number | undefined;
|
|
66
|
-
}):
|
|
74
|
+
}): readable_stream.Writable;
|
|
67
75
|
/**
|
|
68
76
|
* Add a sprite to the styled map package
|
|
69
77
|
*
|
|
@@ -97,7 +105,7 @@ export default class Writer extends EventEmitter<[never]> {
|
|
|
97
105
|
*/
|
|
98
106
|
createGlyphWriteStream({ concurrency }?: {
|
|
99
107
|
concurrency?: number | undefined;
|
|
100
|
-
}):
|
|
108
|
+
}): readable_stream.Writable;
|
|
101
109
|
/**
|
|
102
110
|
* Finalize the styled map package and write the style to the archive.
|
|
103
111
|
* This method must be called to complete the archive.
|
|
@@ -106,24 +114,76 @@ export default class Writer extends EventEmitter<[never]> {
|
|
|
106
114
|
finish(): void;
|
|
107
115
|
#private;
|
|
108
116
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
source:
|
|
117
|
+
type Source = string | Buffer | Uint8Array | stream.Readable;
|
|
118
|
+
type SourceInternal = string | Buffer | stream.Readable;
|
|
119
|
+
type GlyphRange = `${number}-${number}`;
|
|
120
|
+
type TileFormat = "png" | "mvt" | "jpg" | "webp";
|
|
121
|
+
type SourceInfo = {
|
|
122
|
+
source: SMPSource;
|
|
115
123
|
encodedSourceId: string;
|
|
116
124
|
format?: TileFormat | undefined;
|
|
117
125
|
};
|
|
118
|
-
|
|
126
|
+
type TileInfo = {
|
|
119
127
|
z: number;
|
|
120
128
|
x: number;
|
|
121
129
|
y: number;
|
|
122
130
|
sourceId: string;
|
|
123
131
|
format?: TileFormat | undefined;
|
|
124
132
|
};
|
|
125
|
-
|
|
133
|
+
type GlyphInfo = {
|
|
126
134
|
font: string;
|
|
127
135
|
range: GlyphRange;
|
|
128
136
|
};
|
|
129
|
-
|
|
137
|
+
|
|
138
|
+
type TransformInlinedSource<T extends SourceSpecification> = T extends GeoJSONSourceSpecification ? OmitUnion<T, 'data'> & {
|
|
139
|
+
data: GeoJSON;
|
|
140
|
+
} : T extends VectorSourceSpecification | RasterSourceSpecification | RasterDEMSourceSpecification ? SetRequired<OmitUnion<T, 'url'>, 'tiles'> : T;
|
|
141
|
+
/**
|
|
142
|
+
* This is a slightly stricter version of SourceSpecification that requires
|
|
143
|
+
* sources to be inlined (e.g. no urls to TileJSON or GeoJSON files).
|
|
144
|
+
*/
|
|
145
|
+
type InlinedSource = TransformInlinedSource<SourceSpecification>;
|
|
146
|
+
type SupportedInlinedSource = Extract<InlinedSource, {
|
|
147
|
+
type: (typeof SUPPORTED_SOURCE_TYPES)[number];
|
|
148
|
+
}>;
|
|
149
|
+
/**
|
|
150
|
+
* This is a slightly stricter version of StyleSpecification that requires
|
|
151
|
+
* sources to be inlined (e.g. no urls to TileJSON or GeoJSON files).
|
|
152
|
+
*/
|
|
153
|
+
type StyleInlinedSources = Omit<StyleSpecification, 'sources'> & {
|
|
154
|
+
sources: {
|
|
155
|
+
[_: string]: InlinedSource;
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
type SMPSource = TransformSMPInputSource<SupportedInlinedSource>;
|
|
159
|
+
/**
|
|
160
|
+
* This is a slightly stricter version of StyleSpecification that is provided in
|
|
161
|
+
* a Styled Map Package. Tile sources must have tile URLs inlined (they cannot
|
|
162
|
+
* refer to a TileJSON url), and they must have bounds, minzoom, and maxzoom.
|
|
163
|
+
* GeoJSON sources must have inlined GeoJSON (not a URL to a GeoJSON file).
|
|
164
|
+
*/
|
|
165
|
+
type SMPStyle = TransformSMPStyle<StyleSpecification>;
|
|
166
|
+
type TransformSMPInputSource<T extends SupportedInlinedSource> = T extends GeoJSONSourceSpecification ? T & {
|
|
167
|
+
data: {
|
|
168
|
+
bbox: BBox;
|
|
169
|
+
};
|
|
170
|
+
} : T extends RasterSourceSpecification | VectorSourceSpecification ? SetRequired<T, 'bounds' | 'minzoom' | 'maxzoom'> : T;
|
|
171
|
+
type TransformSMPStyle<T extends StyleSpecification> = Omit<T, 'sources'> & {
|
|
172
|
+
metadata: {
|
|
173
|
+
'smp:bounds': [number, number, number, number];
|
|
174
|
+
'smp:maxzoom': 0;
|
|
175
|
+
'smp:sourceFolders': {
|
|
176
|
+
[_: string]: string;
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
sources: {
|
|
180
|
+
[_: string]: SMPSource;
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
interface DownloadStream extends Readable {
|
|
184
|
+
iterator(...args: Parameters<Readable['iterator']>): AsyncIterableIterator<Buffer>;
|
|
185
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<Buffer>;
|
|
186
|
+
}
|
|
187
|
+
type OmitUnion<T, K extends keyof any> = T extends unknown ? Omit<T, K> : never;
|
|
188
|
+
|
|
189
|
+
export { type DownloadStream as D, type GlyphInfo as G, type InlinedSource as I, type SMPSource as S, type TileInfo as T, Writer as W, type SMPStyle as a, type StyleInlinedSources as b, type TileFormat as c, type GlyphRange as d, SUPPORTED_SOURCE_TYPES as e, type Source as f, type SourceInternal as g, type SourceInfo as h };
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { SourceSpecification, GeoJSONSourceSpecification, VectorSourceSpecification, RasterSourceSpecification, RasterDEMSourceSpecification, StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
|
|
2
|
+
import { GeoJSON, BBox } from 'geojson';
|
|
3
|
+
import * as stream from 'stream';
|
|
4
|
+
import { Readable } from 'stream';
|
|
5
|
+
import { SetRequired } from 'type-fest';
|
|
6
|
+
import * as readable_stream from 'readable-stream';
|
|
7
|
+
import { EventEmitter } from 'events';
|
|
8
|
+
|
|
9
|
+
/** @typedef {string | Buffer | Uint8Array | import('stream').Readable } Source */
|
|
10
|
+
/** @typedef {string | Buffer | import('stream').Readable} SourceInternal */
|
|
11
|
+
/** @typedef {`${number}-${number}`} GlyphRange */
|
|
12
|
+
/** @typedef {'png' | 'mvt' | 'jpg' | 'webp'} TileFormat */
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {object} SourceInfo
|
|
15
|
+
* @property {import('./types.js').SMPSource} source
|
|
16
|
+
* @property {string} encodedSourceId
|
|
17
|
+
* @property {TileFormat} [format]
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {object} TileInfo
|
|
21
|
+
* @property {number} z
|
|
22
|
+
* @property {number} x
|
|
23
|
+
* @property {number} y
|
|
24
|
+
* @property {string} sourceId
|
|
25
|
+
* @property {TileFormat} [format]
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {object} GlyphInfo
|
|
29
|
+
* @property {string} font
|
|
30
|
+
* @property {GlyphRange} range
|
|
31
|
+
*/
|
|
32
|
+
/** @import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec' */
|
|
33
|
+
/** @import { InputSource, SMPSource } from './types.js' */
|
|
34
|
+
declare const SUPPORTED_SOURCE_TYPES: readonly ["raster", "vector", "geojson"];
|
|
35
|
+
/**
|
|
36
|
+
* Write a styled map package to a stream. Stream `writer.outputStream` to a
|
|
37
|
+
* destination, e.g. `fs.createWriteStream('my-map.styledmap')`. You must call
|
|
38
|
+
* `witer.finish()` and then wait for your writable stream to `finish` before
|
|
39
|
+
* using the output.
|
|
40
|
+
*/
|
|
41
|
+
declare class Writer extends EventEmitter<[never]> {
|
|
42
|
+
static SUPPORTED_SOURCE_TYPES: readonly ["raster", "vector", "geojson"];
|
|
43
|
+
/**
|
|
44
|
+
* @param {any} style A v7 or v8 MapLibre style. v7 styles will be migrated to
|
|
45
|
+
* v8. (There are currently no typescript declarations for v7 styles, hence
|
|
46
|
+
* this is typed as `any` and validated internally)
|
|
47
|
+
* @param {object} opts
|
|
48
|
+
* @param {number} [opts.highWaterMark=1048576] The maximum number of bytes to buffer during write
|
|
49
|
+
*/
|
|
50
|
+
constructor(style: any, { highWaterMark }?: {
|
|
51
|
+
highWaterMark?: number | undefined;
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* @returns {import('stream').Readable} Readable stream of the styled map package
|
|
55
|
+
*/
|
|
56
|
+
get outputStream(): stream.Readable;
|
|
57
|
+
/**
|
|
58
|
+
* Add a tile to the styled map package
|
|
59
|
+
*
|
|
60
|
+
* @param {Source} tileData
|
|
61
|
+
* @param {TileInfo} opts
|
|
62
|
+
*/
|
|
63
|
+
addTile(tileData: Source, { z, x, y, sourceId, format }: TileInfo): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Create a write stream for adding tiles to the styled map package
|
|
66
|
+
*
|
|
67
|
+
* @param {object} opts
|
|
68
|
+
* @param {number} [opts.concurrency=16] The number of concurrent writes
|
|
69
|
+
*
|
|
70
|
+
* @returns
|
|
71
|
+
*/
|
|
72
|
+
createTileWriteStream({ concurrency }?: {
|
|
73
|
+
concurrency?: number | undefined;
|
|
74
|
+
}): readable_stream.Writable;
|
|
75
|
+
/**
|
|
76
|
+
* Add a sprite to the styled map package
|
|
77
|
+
*
|
|
78
|
+
* @param {object} options
|
|
79
|
+
* @param {Source} options.json
|
|
80
|
+
* @param {Source} options.png
|
|
81
|
+
* @param {number} [options.pixelRatio]
|
|
82
|
+
* @param {string} [options.id='default']
|
|
83
|
+
* @returns {Promise<void>}
|
|
84
|
+
*/
|
|
85
|
+
addSprite({ json, png, pixelRatio, id }: {
|
|
86
|
+
json: Source;
|
|
87
|
+
png: Source;
|
|
88
|
+
pixelRatio?: number | undefined;
|
|
89
|
+
id?: string | undefined;
|
|
90
|
+
}): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Add glyphs to the styled map package
|
|
93
|
+
*
|
|
94
|
+
* @param {Source} glyphData
|
|
95
|
+
* @param {GlyphInfo} glyphInfo
|
|
96
|
+
* @returns {Promise<void>}
|
|
97
|
+
*/
|
|
98
|
+
addGlyphs(glyphData: Source, { font: fontName, range }: GlyphInfo): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Create a write stream for adding glyphs to the styled map package
|
|
101
|
+
*
|
|
102
|
+
* @param {object} opts
|
|
103
|
+
* @param {number} [opts.concurrency=16] The number of concurrent writes
|
|
104
|
+
* @returns
|
|
105
|
+
*/
|
|
106
|
+
createGlyphWriteStream({ concurrency }?: {
|
|
107
|
+
concurrency?: number | undefined;
|
|
108
|
+
}): readable_stream.Writable;
|
|
109
|
+
/**
|
|
110
|
+
* Finalize the styled map package and write the style to the archive.
|
|
111
|
+
* This method must be called to complete the archive.
|
|
112
|
+
* You must wait for your destination write stream to 'finish' before using the output.
|
|
113
|
+
*/
|
|
114
|
+
finish(): void;
|
|
115
|
+
#private;
|
|
116
|
+
}
|
|
117
|
+
type Source = string | Buffer | Uint8Array | stream.Readable;
|
|
118
|
+
type SourceInternal = string | Buffer | stream.Readable;
|
|
119
|
+
type GlyphRange = `${number}-${number}`;
|
|
120
|
+
type TileFormat = "png" | "mvt" | "jpg" | "webp";
|
|
121
|
+
type SourceInfo = {
|
|
122
|
+
source: SMPSource;
|
|
123
|
+
encodedSourceId: string;
|
|
124
|
+
format?: TileFormat | undefined;
|
|
125
|
+
};
|
|
126
|
+
type TileInfo = {
|
|
127
|
+
z: number;
|
|
128
|
+
x: number;
|
|
129
|
+
y: number;
|
|
130
|
+
sourceId: string;
|
|
131
|
+
format?: TileFormat | undefined;
|
|
132
|
+
};
|
|
133
|
+
type GlyphInfo = {
|
|
134
|
+
font: string;
|
|
135
|
+
range: GlyphRange;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
type TransformInlinedSource<T extends SourceSpecification> = T extends GeoJSONSourceSpecification ? OmitUnion<T, 'data'> & {
|
|
139
|
+
data: GeoJSON;
|
|
140
|
+
} : T extends VectorSourceSpecification | RasterSourceSpecification | RasterDEMSourceSpecification ? SetRequired<OmitUnion<T, 'url'>, 'tiles'> : T;
|
|
141
|
+
/**
|
|
142
|
+
* This is a slightly stricter version of SourceSpecification that requires
|
|
143
|
+
* sources to be inlined (e.g. no urls to TileJSON or GeoJSON files).
|
|
144
|
+
*/
|
|
145
|
+
type InlinedSource = TransformInlinedSource<SourceSpecification>;
|
|
146
|
+
type SupportedInlinedSource = Extract<InlinedSource, {
|
|
147
|
+
type: (typeof SUPPORTED_SOURCE_TYPES)[number];
|
|
148
|
+
}>;
|
|
149
|
+
/**
|
|
150
|
+
* This is a slightly stricter version of StyleSpecification that requires
|
|
151
|
+
* sources to be inlined (e.g. no urls to TileJSON or GeoJSON files).
|
|
152
|
+
*/
|
|
153
|
+
type StyleInlinedSources = Omit<StyleSpecification, 'sources'> & {
|
|
154
|
+
sources: {
|
|
155
|
+
[_: string]: InlinedSource;
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
type SMPSource = TransformSMPInputSource<SupportedInlinedSource>;
|
|
159
|
+
/**
|
|
160
|
+
* This is a slightly stricter version of StyleSpecification that is provided in
|
|
161
|
+
* a Styled Map Package. Tile sources must have tile URLs inlined (they cannot
|
|
162
|
+
* refer to a TileJSON url), and they must have bounds, minzoom, and maxzoom.
|
|
163
|
+
* GeoJSON sources must have inlined GeoJSON (not a URL to a GeoJSON file).
|
|
164
|
+
*/
|
|
165
|
+
type SMPStyle = TransformSMPStyle<StyleSpecification>;
|
|
166
|
+
type TransformSMPInputSource<T extends SupportedInlinedSource> = T extends GeoJSONSourceSpecification ? T & {
|
|
167
|
+
data: {
|
|
168
|
+
bbox: BBox;
|
|
169
|
+
};
|
|
170
|
+
} : T extends RasterSourceSpecification | VectorSourceSpecification ? SetRequired<T, 'bounds' | 'minzoom' | 'maxzoom'> : T;
|
|
171
|
+
type TransformSMPStyle<T extends StyleSpecification> = Omit<T, 'sources'> & {
|
|
172
|
+
metadata: {
|
|
173
|
+
'smp:bounds': [number, number, number, number];
|
|
174
|
+
'smp:maxzoom': 0;
|
|
175
|
+
'smp:sourceFolders': {
|
|
176
|
+
[_: string]: string;
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
sources: {
|
|
180
|
+
[_: string]: SMPSource;
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
interface DownloadStream extends Readable {
|
|
184
|
+
iterator(...args: Parameters<Readable['iterator']>): AsyncIterableIterator<Buffer>;
|
|
185
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<Buffer>;
|
|
186
|
+
}
|
|
187
|
+
type OmitUnion<T, K extends keyof any> = T extends unknown ? Omit<T, K> : never;
|
|
188
|
+
|
|
189
|
+
export { type DownloadStream as D, type GlyphInfo as G, type InlinedSource as I, type SMPSource as S, type TileInfo as T, Writer as W, type SMPStyle as a, type StyleInlinedSources as b, type TileFormat as c, type GlyphRange as d, SUPPORTED_SOURCE_TYPES as e, type Source as f, type SourceInternal as g, type SourceInfo as h };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var errors_exports = {};
|
|
20
|
+
__export(errors_exports, {
|
|
21
|
+
ENOENT: () => ENOENT,
|
|
22
|
+
isFileNotThereError: () => isFileNotThereError
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(errors_exports);
|
|
25
|
+
class ENOENT extends Error {
|
|
26
|
+
code = "ENOENT";
|
|
27
|
+
/** @param {string} path */
|
|
28
|
+
constructor(path) {
|
|
29
|
+
const message = `ENOENT: no such file or directory, open '${path}'`;
|
|
30
|
+
super(message);
|
|
31
|
+
this.path = path;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function isFileNotThereError(error) {
|
|
35
|
+
return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "EPERM");
|
|
36
|
+
}
|
|
37
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
38
|
+
0 && (module.exports = {
|
|
39
|
+
ENOENT,
|
|
40
|
+
isFileNotThereError
|
|
41
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
declare function isFileNotThereError(error: unknown): error is Error & {
|
|
9
|
+
code: "ENOENT" | "EPERM";
|
|
10
|
+
};
|
|
11
|
+
declare class ENOENT extends Error {
|
|
12
|
+
/** @param {string} path */
|
|
13
|
+
constructor(path: string);
|
|
14
|
+
code: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { ENOENT, isFileNotThereError };
|
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
* @param {unknown} error
|
|
6
6
|
* @returns {error is Error & { code: 'ENOENT' | 'EPERM' }}
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
declare function isFileNotThereError(error: unknown): error is Error & {
|
|
9
9
|
code: "ENOENT" | "EPERM";
|
|
10
10
|
};
|
|
11
|
-
|
|
11
|
+
declare class ENOENT extends Error {
|
|
12
12
|
/** @param {string} path */
|
|
13
13
|
constructor(path: string);
|
|
14
14
|
code: string;
|
|
15
15
|
path: string;
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
export { ENOENT, isFileNotThereError };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class ENOENT extends Error {
|
|
2
|
+
code = "ENOENT";
|
|
3
|
+
/** @param {string} path */
|
|
4
|
+
constructor(path) {
|
|
5
|
+
const message = `ENOENT: no such file or directory, open '${path}'`;
|
|
6
|
+
super(message);
|
|
7
|
+
this.path = path;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function isFileNotThereError(error) {
|
|
11
|
+
return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "EPERM");
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
ENOENT,
|
|
15
|
+
isFileNotThereError
|
|
16
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
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 fetch_exports = {};
|
|
30
|
+
__export(fetch_exports, {
|
|
31
|
+
FetchQueue: () => FetchQueue
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(fetch_exports);
|
|
34
|
+
var import_ky = __toESM(require("ky"), 1);
|
|
35
|
+
var import_p_event = require("p-event");
|
|
36
|
+
var import_p_limit = __toESM(require("p-limit"), 1);
|
|
37
|
+
var import_streams = require('./streams.cjs');
|
|
38
|
+
class FetchQueue {
|
|
39
|
+
/** @type {import('p-limit').LimitFunction} */
|
|
40
|
+
#limit;
|
|
41
|
+
/** @param {number} concurrency */
|
|
42
|
+
constructor(concurrency) {
|
|
43
|
+
this.#limit = (0, import_p_limit.default)(concurrency);
|
|
44
|
+
}
|
|
45
|
+
get activeCount() {
|
|
46
|
+
return this.#limit.activeCount;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Fetch a URL, limiting the number of concurrent downloads. Resolves with a
|
|
50
|
+
* `DownloadResponse`, which is a parsed from the Fetch `Response` objects,
|
|
51
|
+
* with `body` as a Node readable stream, and the MIME type and content length
|
|
52
|
+
* of the response.
|
|
53
|
+
*
|
|
54
|
+
* NB: The response body stream must be consumed to the end, otherwise the
|
|
55
|
+
* queue will never be emptied.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} url
|
|
58
|
+
* @param {{ onprogress?: import('./streams.js').ProgressCallback }} opts
|
|
59
|
+
* @returns {Promise<DownloadResponse>}
|
|
60
|
+
*/
|
|
61
|
+
fetch(url, { onprogress } = {}) {
|
|
62
|
+
return new Promise((resolveResponse, rejectResponse) => {
|
|
63
|
+
this.#limit(fetchStream, {
|
|
64
|
+
url,
|
|
65
|
+
onresponse: resolveResponse,
|
|
66
|
+
onerror: rejectResponse,
|
|
67
|
+
onprogress
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function fetchStream({ url, onresponse, onerror, onprogress }) {
|
|
73
|
+
try {
|
|
74
|
+
const response = await (0, import_ky.default)(url, { retry: 3 });
|
|
75
|
+
if (!response.body) {
|
|
76
|
+
throw new Error("No body in response");
|
|
77
|
+
}
|
|
78
|
+
const body = (0, import_streams.fromWebReadableStream)(response.body);
|
|
79
|
+
const contentType = response.headers.get("content-type");
|
|
80
|
+
const mimeType = typeof contentType === "string" ? contentType.split(";")[0] : null;
|
|
81
|
+
const contentLengthHeader = response.headers.get("content-length");
|
|
82
|
+
const contentLength = contentLengthHeader === null ? null : parseInt(contentLengthHeader, 10);
|
|
83
|
+
onresponse({
|
|
84
|
+
body: onprogress ? body.pipe(new import_streams.ProgressStream({ onprogress })) : body,
|
|
85
|
+
mimeType,
|
|
86
|
+
contentLength
|
|
87
|
+
});
|
|
88
|
+
await (0, import_p_event.pEvent)(body, "end");
|
|
89
|
+
} catch (err) {
|
|
90
|
+
onerror(err instanceof Error ? err : new Error("Unknown error"));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
94
|
+
0 && (module.exports = {
|
|
95
|
+
FetchQueue
|
|
96
|
+
});
|