@versatiles/container 1.2.8 → 1.4.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/dist/index.d.ts +3 -3
- package/dist/index.js +98 -24
- package/dist/lib/decompress.js +1 -1
- package/dist/lib/reader_http.js +16 -14
- package/package.json +16 -12
package/dist/index.d.ts
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
36
|
import type { Block, Header, OpenOptions, Reader, TileIndex } from './lib/interfaces.js';
|
|
37
|
-
export type { Block, Compression, Format, Header, OpenOptions, Reader, TileIndex } from './lib/interfaces.js';
|
|
37
|
+
export type { Block, Compression, Format, Header, OpenOptions, Reader, TileIndex, } from './lib/interfaces.js';
|
|
38
38
|
/**
|
|
39
39
|
* The `VersaTiles` class is a wrapper around a `.versatiles` container file. It provides methods
|
|
40
40
|
* to access tile data, metadata, and other properties within the container.
|
|
@@ -96,7 +96,7 @@ export declare class Container {
|
|
|
96
96
|
* @returns A promise that resolves with the block index map.
|
|
97
97
|
* @protected
|
|
98
98
|
*/
|
|
99
|
-
|
|
99
|
+
getBlockIndex(): Promise<Map<string, Block>>;
|
|
100
100
|
/**
|
|
101
101
|
* Asynchronously retrieves the tile index for a specified block. This is an internal method used to
|
|
102
102
|
* maintain a lookup for every tile within a block.
|
|
@@ -105,7 +105,7 @@ export declare class Container {
|
|
|
105
105
|
* @returns A promise that resolves with the tile index.
|
|
106
106
|
* @protected
|
|
107
107
|
*/
|
|
108
|
-
|
|
108
|
+
getTileIndex(block: Block): Promise<TileIndex>;
|
|
109
109
|
/**
|
|
110
110
|
* A protected method to read a chunk of data from the source based on the specified offset and length.
|
|
111
111
|
*
|
package/dist/index.js
CHANGED
|
@@ -37,26 +37,77 @@ import HttpReader from './lib/reader_http.js';
|
|
|
37
37
|
import FileReader from './lib/reader_file.js';
|
|
38
38
|
import { decompress } from './lib/decompress.js';
|
|
39
39
|
const FORMATS = {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
'
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
c01: [
|
|
41
|
+
'png',
|
|
42
|
+
'jpg',
|
|
43
|
+
'webp',
|
|
44
|
+
null,
|
|
45
|
+
null,
|
|
46
|
+
null,
|
|
47
|
+
null,
|
|
48
|
+
null,
|
|
49
|
+
null,
|
|
50
|
+
null,
|
|
51
|
+
null,
|
|
52
|
+
null,
|
|
53
|
+
null,
|
|
54
|
+
null,
|
|
55
|
+
null,
|
|
56
|
+
null,
|
|
57
|
+
'pbf',
|
|
58
|
+
],
|
|
59
|
+
v01: ['png', 'jpg', 'webp', 'pbf'],
|
|
60
|
+
v02: [
|
|
61
|
+
'bin',
|
|
62
|
+
null,
|
|
63
|
+
null,
|
|
64
|
+
null,
|
|
65
|
+
null,
|
|
66
|
+
null,
|
|
67
|
+
null,
|
|
68
|
+
null,
|
|
69
|
+
null,
|
|
70
|
+
null,
|
|
71
|
+
null,
|
|
72
|
+
null,
|
|
73
|
+
null,
|
|
74
|
+
null,
|
|
75
|
+
null,
|
|
76
|
+
null,
|
|
77
|
+
'png',
|
|
78
|
+
'jpg',
|
|
79
|
+
'webp',
|
|
80
|
+
'avif',
|
|
81
|
+
'svg',
|
|
82
|
+
null,
|
|
83
|
+
null,
|
|
84
|
+
null,
|
|
85
|
+
null,
|
|
86
|
+
null,
|
|
87
|
+
null,
|
|
88
|
+
null,
|
|
89
|
+
null,
|
|
90
|
+
null,
|
|
91
|
+
null,
|
|
92
|
+
null,
|
|
93
|
+
'pbf',
|
|
94
|
+
'geojson',
|
|
95
|
+
'topojson',
|
|
96
|
+
'json',
|
|
46
97
|
],
|
|
47
98
|
};
|
|
48
99
|
const COMPRESSIONS = ['raw', 'gzip', 'br'];
|
|
49
100
|
const MIMETYPES = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
101
|
+
avif: 'image/avif',
|
|
102
|
+
bin: 'application/octet-stream',
|
|
103
|
+
geojson: 'application/geo+json; charset=utf-8',
|
|
104
|
+
jpg: 'image/jpeg',
|
|
105
|
+
json: 'application/json; charset=utf-8',
|
|
106
|
+
pbf: 'application/x-protobuf',
|
|
107
|
+
png: 'image/png',
|
|
108
|
+
svg: 'image/svg+xml; charset=utf-8',
|
|
109
|
+
topojson: 'application/topo+json; charset=utf-8',
|
|
110
|
+
webp: 'image/webp',
|
|
60
111
|
};
|
|
61
112
|
/**
|
|
62
113
|
* The `VersaTiles` class is a wrapper around a `.versatiles` container file. It provides methods
|
|
@@ -125,15 +176,38 @@ export class Container {
|
|
|
125
176
|
const blockIndexLength = Number(data.readBigUInt64BE(58));
|
|
126
177
|
switch (version) {
|
|
127
178
|
case 'v01':
|
|
128
|
-
bbox = [
|
|
179
|
+
bbox = [
|
|
180
|
+
data.readFloatBE(18),
|
|
181
|
+
data.readFloatBE(22),
|
|
182
|
+
data.readFloatBE(26),
|
|
183
|
+
data.readFloatBE(30),
|
|
184
|
+
];
|
|
129
185
|
break;
|
|
130
186
|
case 'v02':
|
|
131
|
-
bbox = [
|
|
187
|
+
bbox = [
|
|
188
|
+
data.readInt32BE(18) / 1e7,
|
|
189
|
+
data.readInt32BE(22) / 1e7,
|
|
190
|
+
data.readInt32BE(26) / 1e7,
|
|
191
|
+
data.readInt32BE(30) / 1e7,
|
|
192
|
+
];
|
|
132
193
|
break;
|
|
133
194
|
default:
|
|
134
195
|
throw new Error('Invalid Container');
|
|
135
196
|
}
|
|
136
|
-
this.#header = {
|
|
197
|
+
this.#header = {
|
|
198
|
+
magic,
|
|
199
|
+
version,
|
|
200
|
+
tileFormat,
|
|
201
|
+
tileMime,
|
|
202
|
+
tileCompression,
|
|
203
|
+
zoomMin,
|
|
204
|
+
zoomMax,
|
|
205
|
+
bbox,
|
|
206
|
+
metaOffset,
|
|
207
|
+
metaLength,
|
|
208
|
+
blockIndexOffset,
|
|
209
|
+
blockIndexLength,
|
|
210
|
+
};
|
|
137
211
|
return this.#header;
|
|
138
212
|
}
|
|
139
213
|
/**
|
|
@@ -178,8 +252,8 @@ export class Container {
|
|
|
178
252
|
const bx = x >> 8;
|
|
179
253
|
const by = y >> 8;
|
|
180
254
|
// tile xy (within block)
|
|
181
|
-
const tx = x &
|
|
182
|
-
const ty = y &
|
|
255
|
+
const tx = x & 0xff;
|
|
256
|
+
const ty = y & 0xff;
|
|
183
257
|
// check if block containing tile is within bounds
|
|
184
258
|
const blockKey = `${z},${bx},${by}`;
|
|
185
259
|
const block = blockIndex.get(blockKey);
|
|
@@ -237,7 +311,7 @@ export class Container {
|
|
|
237
311
|
switch (header.version) {
|
|
238
312
|
case 'c01':
|
|
239
313
|
case 'v01':
|
|
240
|
-
// check
|
|
314
|
+
// check block index length
|
|
241
315
|
if (data.length % 29 !== 0)
|
|
242
316
|
throw new Error('invalid block index');
|
|
243
317
|
for (let i = 0; i < data.length; i += 29) {
|
|
@@ -246,7 +320,7 @@ export class Container {
|
|
|
246
320
|
}
|
|
247
321
|
break;
|
|
248
322
|
case 'v02':
|
|
249
|
-
// check
|
|
323
|
+
// check block index length
|
|
250
324
|
if (data.length % 33 !== 0)
|
|
251
325
|
throw new Error('invalid block index');
|
|
252
326
|
for (let i = 0; i < data.length; i += 33) {
|
|
@@ -257,7 +331,7 @@ export class Container {
|
|
|
257
331
|
break;
|
|
258
332
|
}
|
|
259
333
|
// build map
|
|
260
|
-
this.#blockIndex = new Map(blocks.map(b => [`${b.level},${b.column},${b.row}`, b]));
|
|
334
|
+
this.#blockIndex = new Map(blocks.map((b) => [`${b.level},${b.column},${b.row}`, b]));
|
|
261
335
|
return this.#blockIndex;
|
|
262
336
|
function addBlock(buffer, blockOffset, tileIndexOffset, tileIndexLength) {
|
|
263
337
|
const block = {
|
package/dist/lib/decompress.js
CHANGED
|
@@ -34,7 +34,7 @@ export async function decompress(buffer, compression) {
|
|
|
34
34
|
*/
|
|
35
35
|
function handle(error, result) {
|
|
36
36
|
if (error) {
|
|
37
|
-
reject(`Can not decompress buffer (length=${buffer.length}) with "${compression}"`);
|
|
37
|
+
reject(new Error(`Can not decompress buffer (length=${buffer.length}) with "${compression}": ${error.message}`));
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
else {
|
package/dist/lib/reader_http.js
CHANGED
|
@@ -17,6 +17,10 @@ const clients = {
|
|
|
17
17
|
* @returns A `Reader` function that asynchronously reads a specified chunk of data from the URL.
|
|
18
18
|
*/
|
|
19
19
|
export default function getHTTPReader(url) {
|
|
20
|
+
const protocol = new URL(url).protocol.slice(0, -1);
|
|
21
|
+
if (!(protocol in clients)) {
|
|
22
|
+
throw new Error(`Unsupported protocol: ${protocol}`);
|
|
23
|
+
}
|
|
20
24
|
/**
|
|
21
25
|
* Asynchronously reads a data chunk from the provided URL based on the specified range.
|
|
22
26
|
*
|
|
@@ -35,37 +39,39 @@ export default function getHTTPReader(url) {
|
|
|
35
39
|
}
|
|
36
40
|
const headers = {
|
|
37
41
|
'user-agent': 'Mozilla/5.0 (compatible; versatiles; +https://www.npmjs.com/package/versatiles)',
|
|
38
|
-
|
|
42
|
+
range: `bytes=${position}-${position + length - 1}`,
|
|
39
43
|
};
|
|
40
|
-
const protocol = new URL(url).protocol.slice(0, -1);
|
|
41
|
-
if (!(protocol in clients)) {
|
|
42
|
-
throw new Error(`Unsupported protocol: ${protocol}`);
|
|
43
|
-
}
|
|
44
44
|
/**
|
|
45
45
|
* Performs the HTTP request and retrieves the response.
|
|
46
46
|
* @type {IncomingMessage}
|
|
47
47
|
*/
|
|
48
48
|
const message = await new Promise((resolve, reject) => {
|
|
49
49
|
const watchdog = setTimeout(() => {
|
|
50
|
+
req.destroy();
|
|
50
51
|
reject(new Error('Request timed out'));
|
|
51
52
|
}, DEFAULT_TIMEOUT);
|
|
52
|
-
clients[protocol].client
|
|
53
|
+
const req = clients[protocol].client
|
|
53
54
|
.request(url, {
|
|
54
55
|
method: 'GET',
|
|
55
56
|
agent: clients[protocol].agent,
|
|
56
57
|
headers,
|
|
57
58
|
timeout: DEFAULT_TIMEOUT,
|
|
58
59
|
})
|
|
59
|
-
.on('response', response => {
|
|
60
|
+
.on('response', (response) => {
|
|
60
61
|
clearTimeout(watchdog);
|
|
61
62
|
resolve(response);
|
|
62
63
|
})
|
|
63
|
-
.on('error', err => {
|
|
64
|
+
.on('error', (err) => {
|
|
64
65
|
clearTimeout(watchdog);
|
|
66
|
+
req.destroy();
|
|
65
67
|
reject(err);
|
|
66
68
|
})
|
|
67
69
|
.end();
|
|
68
70
|
});
|
|
71
|
+
if (message.statusCode == null || Math.floor(message.statusCode / 100) !== 2) {
|
|
72
|
+
message.destroy();
|
|
73
|
+
throw new Error(`Server responded with status code: ${message.statusCode} `);
|
|
74
|
+
}
|
|
69
75
|
const contentRange = message.headers['content-range'];
|
|
70
76
|
if (contentRange == null)
|
|
71
77
|
throw Error('The response header does not contain "content-range"');
|
|
@@ -73,7 +79,7 @@ export default function getHTTPReader(url) {
|
|
|
73
79
|
if (parts == null)
|
|
74
80
|
throw Error('"content-range" in response header is malformed');
|
|
75
81
|
if (position !== parseInt(parts[1], 10))
|
|
76
|
-
throw Error(`
|
|
82
|
+
throw Error(`requested position (${position}) and returned offset (${parts[1]}) must be equal`);
|
|
77
83
|
if (position + length > parseInt(parts[3], 10)) {
|
|
78
84
|
throw new RangeError(`Read range out of bounds: The requested range ends at position ${position + length}, which exceeds the file's limit of ${parts[3]} bytes.`);
|
|
79
85
|
}
|
|
@@ -81,10 +87,6 @@ export default function getHTTPReader(url) {
|
|
|
81
87
|
if (length !== returnedLength) {
|
|
82
88
|
throw new Error(`Returned length (${returnedLength}) is not requested length (${length}).`);
|
|
83
89
|
}
|
|
84
|
-
if ((message.statusCode == null) || Math.floor(message.statusCode / 100) !== 2) {
|
|
85
|
-
message.destroy();
|
|
86
|
-
throw new Error(`Server responded with status code: ${message.statusCode} `);
|
|
87
|
-
}
|
|
88
90
|
/**
|
|
89
91
|
* Collects and concatenates response data chunks into a buffer.
|
|
90
92
|
* @type {Buffer}
|
|
@@ -93,7 +95,7 @@ export default function getHTTPReader(url) {
|
|
|
93
95
|
const buffers = [];
|
|
94
96
|
message
|
|
95
97
|
.on('data', (chunk) => buffers.push(chunk))
|
|
96
|
-
.on('error', err => {
|
|
98
|
+
.on('error', (err) => {
|
|
97
99
|
message.destroy();
|
|
98
100
|
reject(err);
|
|
99
101
|
})
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versatiles/container",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A client library for reading VersaTiles containers",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "rm -rf dist && tsc -p tsconfig.build.json && npm run doc-graph",
|
|
7
|
-
"check": "npm run lint && npm run build && npm run test",
|
|
7
|
+
"check": "npm run format:check && npm run lint && npm run build && npm run test",
|
|
8
8
|
"doc": "npm run doc-typescript && npm run doc-graph",
|
|
9
9
|
"doc-typescript": "vrt doc-typescript -f html",
|
|
10
10
|
"doc-graph": "vrt deps-graph | vrt doc-insert README.md '## Dependency Graph'",
|
|
11
|
+
"format": "prettier --write 'src/**/*.ts'",
|
|
12
|
+
"format:check": "prettier --check 'src/**/*.ts'",
|
|
11
13
|
"lint": "eslint . --color",
|
|
12
14
|
"prepack": "npm run build",
|
|
13
15
|
"release": "vrt release-npm",
|
|
@@ -23,7 +25,7 @@
|
|
|
23
25
|
"type": "git",
|
|
24
26
|
"url": "git+https://github.com/versatiles-org/node-versatiles-container.git"
|
|
25
27
|
},
|
|
26
|
-
"homepage": "https://github.com/versatiles-org/node-versatiles-container
|
|
28
|
+
"homepage": "https://github.com/versatiles-org/node-versatiles-container",
|
|
27
29
|
"main": "dist/index.js",
|
|
28
30
|
"types": "dist/index.d.ts",
|
|
29
31
|
"type": "module",
|
|
@@ -51,16 +53,18 @@
|
|
|
51
53
|
"versatiles"
|
|
52
54
|
],
|
|
53
55
|
"devDependencies": {
|
|
54
|
-
"@types/node": "^
|
|
55
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
56
|
-
"@typescript-eslint/parser": "^8.
|
|
57
|
-
"@versatiles/release-tool": "^2.
|
|
58
|
-
"@vitest/coverage-v8": "^4.0.
|
|
59
|
-
"eslint": "^9.39.
|
|
56
|
+
"@types/node": "^25.2.3",
|
|
57
|
+
"@typescript-eslint/eslint-plugin": "^8.55.0",
|
|
58
|
+
"@typescript-eslint/parser": "^8.55.0",
|
|
59
|
+
"@versatiles/release-tool": "^2.7.1",
|
|
60
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
61
|
+
"eslint": "^9.39.2",
|
|
62
|
+
"eslint-config-prettier": "^10.1.8",
|
|
63
|
+
"prettier": "^3.8.1",
|
|
60
64
|
"ts-node": "^10.9.2",
|
|
61
|
-
"tsx": "^4.
|
|
65
|
+
"tsx": "^4.21.0",
|
|
62
66
|
"typescript": "^5.9.3",
|
|
63
|
-
"typescript-eslint": "^8.
|
|
64
|
-
"vitest": "^4.0.
|
|
67
|
+
"typescript-eslint": "^8.55.0",
|
|
68
|
+
"vitest": "^4.0.18"
|
|
65
69
|
}
|
|
66
70
|
}
|