pmtiles-swarm 0.98.1 β 0.98.3
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/CHANGELOG.md +31 -0
- package/package.json +1 -1
- package/src/web/index.html +87 -16
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,37 @@
|
|
|
7
7
|
### π Bug fixes
|
|
8
8
|
- _...Add new stuff here..._
|
|
9
9
|
|
|
10
|
+
## 0.98.3
|
|
11
|
+
### β¨ Features and improvements
|
|
12
|
+
|
|
13
|
+
### π Bug fixes
|
|
14
|
+
- **A stack could not be pointed at a completed MBTiles archive.** The source picker offered only
|
|
15
|
+
PMTiles, so an MBTiles the node was perfectly able to serve tiles from was simply absent from the
|
|
16
|
+
menu. It offers a complete one now, by the same rule the tile route enforces β and still hides one
|
|
17
|
+
that is arriving, since a stack naming that would answer 503 for every tile until the download
|
|
18
|
+
finished.
|
|
19
|
+
- **A planet dump was offered as a stack source.** The same filter read an archive with no recorded
|
|
20
|
+
kind as PMTiles, which is not a harmless default: a mirrored `.osm.pbf` appeared in the menu, and
|
|
21
|
+
naming it would have produced a recipe that failed at its first tile. The kind now falls back to
|
|
22
|
+
the filename before anything is assumed, which is how `prewarm.js` resolves it after the identical
|
|
23
|
+
mistake sent every mirrored dump round the header-read backoff for ever. Such an archive is also
|
|
24
|
+
labelled `unknown Β· not servable` in the list, where it previously said nothing at all.
|
|
25
|
+
|
|
26
|
+
## 0.98.2
|
|
27
|
+
### β¨ Features and improvements
|
|
28
|
+
|
|
29
|
+
### π Bug fixes
|
|
30
|
+
- **The console called a complete MBTiles archive "not servable".** It is, and has been since the
|
|
31
|
+
tile store learned to open one: PMTiles always, MBTiles from a complete local copy. The console
|
|
32
|
+
never followed. It tested `kind === 'pmtiles'` in two places, so an MBTiles that had finished
|
|
33
|
+
hashing was labelled `mbtiles Β· not servable` in the list and had its TileJSON, preview and tile
|
|
34
|
+
endpoint hidden in the panel β all of which the node was answering perfectly well.
|
|
35
|
+
|
|
36
|
+
One rule now, matching what the tile route actually enforces, and an archive still arriving reads
|
|
37
|
+
as `servable once complete` rather than as one that never will be. Warming stays PMTiles-only: it
|
|
38
|
+
fetches the pieces a region's tiles live in, and an MBTiles is read whole or not at all, so there
|
|
39
|
+
is never a region of one to warm.
|
|
40
|
+
|
|
10
41
|
## 0.98.1
|
|
11
42
|
### β¨ Features and improvements
|
|
12
43
|
- **The two archive readers no longer import each other.** Summarising an MBTiles archive reached
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmtiles-swarm",
|
|
3
|
-
"version": "0.98.
|
|
3
|
+
"version": "0.98.3",
|
|
4
4
|
"description": "BitTorrent distribution for PMTiles map archives: create torrents, watch folders, publish and subscribe to RSS feeds, and seed through qBittorrent or an embedded client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
package/src/web/index.html
CHANGED
|
@@ -1823,6 +1823,63 @@
|
|
|
1823
1823
|
}
|
|
1824
1824
|
};
|
|
1825
1825
|
|
|
1826
|
+
/**
|
|
1827
|
+
* Whether this archive has a tile endpoint at all.
|
|
1828
|
+
*
|
|
1829
|
+
* The same rule the tile route applies, rather than a second opinion
|
|
1830
|
+
* about it: PMTiles always, MBTiles once the file is whole. MBTiles is
|
|
1831
|
+
* SQLite, so it cannot be read a byte range at a time out of the swarm β
|
|
1832
|
+
* but a complete one on local disk is an ordinary database holding the
|
|
1833
|
+
* same tiles, and refusing to serve it is refusing something that works.
|
|
1834
|
+
* See docs/internals.md β "Serving an MBTiles archive".
|
|
1835
|
+
* @param {object} entry - A catalog entry.
|
|
1836
|
+
* @returns {boolean} - Whether to offer the tile endpoints.
|
|
1837
|
+
*/
|
|
1838
|
+
const isServable = (entry) => {
|
|
1839
|
+
const kind = kindOf(entry);
|
|
1840
|
+
if (kind === 'pmtiles') return true;
|
|
1841
|
+
return kind === 'mbtiles' && entry.complete === true;
|
|
1842
|
+
};
|
|
1843
|
+
|
|
1844
|
+
/**
|
|
1845
|
+
* What kind of archive this is, from the record or failing that the name.
|
|
1846
|
+
*
|
|
1847
|
+
* An entry from before the kind was recorded carries none, and reading
|
|
1848
|
+
* that as PMTiles is not a harmless default: it is how a planet dump ends
|
|
1849
|
+
* up labelled servable and offered as a stack source, where naming it
|
|
1850
|
+
* would produce a recipe that fails at its first tile. `prewarm.js`
|
|
1851
|
+
* resolves it exactly this way, after the same mistake sent every
|
|
1852
|
+
* mirrored .osm.pbf round the header-read backoff for ever.
|
|
1853
|
+
* @param {object} entry - A catalog entry.
|
|
1854
|
+
* @returns {string} - 'pmtiles', 'mbtiles', or 'unknown'.
|
|
1855
|
+
*/
|
|
1856
|
+
const kindOf = (entry) => {
|
|
1857
|
+
if (entry.kind) return entry.kind;
|
|
1858
|
+
const name = entry.name ?? '';
|
|
1859
|
+
if (/\.pmtiles$/i.test(name)) return 'pmtiles';
|
|
1860
|
+
if (/\.mbtiles$/i.test(name)) return 'mbtiles';
|
|
1861
|
+
return 'unknown';
|
|
1862
|
+
};
|
|
1863
|
+
|
|
1864
|
+
/**
|
|
1865
|
+
* What to say under the size about an archive that is not PMTiles.
|
|
1866
|
+
*
|
|
1867
|
+
* An MBTiles that is here in full is servable, and saying "not servable"
|
|
1868
|
+
* beside a finished file was simply wrong. One that is still arriving is
|
|
1869
|
+
* not servable *yet*, which is a different thing to tell somebody: it
|
|
1870
|
+
* becomes one by waiting, where an .osm.pbf never will.
|
|
1871
|
+
* @param {object} entry - A catalog entry.
|
|
1872
|
+
* @returns {string} - The note, or empty for a PMTiles archive.
|
|
1873
|
+
*/
|
|
1874
|
+
const kindNote = (entry) => {
|
|
1875
|
+
const kind = kindOf(entry);
|
|
1876
|
+
if (kind === 'pmtiles') return '';
|
|
1877
|
+
if (kind !== 'mbtiles') return `${escapeHtml(kind)} Β· not servable`;
|
|
1878
|
+
return entry.complete === true
|
|
1879
|
+
? escapeHtml(kind)
|
|
1880
|
+
: `${escapeHtml(kind)} Β· servable once complete`;
|
|
1881
|
+
};
|
|
1882
|
+
|
|
1826
1883
|
/**
|
|
1827
1884
|
* Closes the details, panel and row together.
|
|
1828
1885
|
*
|
|
@@ -1891,8 +1948,8 @@
|
|
|
1891
1948
|
.join(' Β· ')}</div>
|
|
1892
1949
|
</td>
|
|
1893
1950
|
<td>${bytes(entry.size)}${
|
|
1894
|
-
(entry
|
|
1895
|
-
? `<div class="sub">${
|
|
1951
|
+
kindNote(entry)
|
|
1952
|
+
? `<div class="sub">${kindNote(entry)}</div>`
|
|
1896
1953
|
: ''
|
|
1897
1954
|
}</td>
|
|
1898
1955
|
<td>${added(entry.createdAt)}</td>
|
|
@@ -2518,10 +2575,15 @@
|
|
|
2518
2575
|
|
|
2519
2576
|
const base = location.origin;
|
|
2520
2577
|
const tileJson = `${base}/archives/${entry.infoHash}/tiles.json`;
|
|
2521
|
-
//
|
|
2522
|
-
//
|
|
2523
|
-
//
|
|
2524
|
-
const servable = (entry
|
|
2578
|
+
// Offering the URL for something that cannot serve tiles hands out a
|
|
2579
|
+
// link that will never work and reads as a fault in the server rather
|
|
2580
|
+
// than a fact about the archive.
|
|
2581
|
+
const servable = isServable(entry);
|
|
2582
|
+
// Warming pulls the pieces a region's tiles live in, so it only means
|
|
2583
|
+
// anything for an archive read out of the swarm. An MBTiles is read
|
|
2584
|
+
// whole or not at all β once it is here there is nothing left to
|
|
2585
|
+
// fetch, and before that there is no tile to warm.
|
|
2586
|
+
const warmable = kindOf(entry) === 'pmtiles';
|
|
2525
2587
|
const torrentUrl = `${base}/archives/${entry.infoHash}/archive.torrent`;
|
|
2526
2588
|
const summary = entry.pmtiles ?? {};
|
|
2527
2589
|
const mode = entry.mode ?? 'mirror';
|
|
@@ -2606,11 +2668,18 @@
|
|
|
2606
2668
|
${
|
|
2607
2669
|
servable
|
|
2608
2670
|
? `<div class="sub" style="margin-bottom:1rem"><code>${escapeHtml(tileJson)}</code></div>`
|
|
2609
|
-
:
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2671
|
+
: kindOf(entry) === 'mbtiles'
|
|
2672
|
+
? `<div class="sub" style="margin-bottom:1rem">
|
|
2673
|
+
This MBTiles archive is still arriving, so it has no tile endpoint yet. It is
|
|
2674
|
+
SQLite, which cannot be read a byte range at a time out of the swarm the way
|
|
2675
|
+
PMTiles can β so it becomes servable when the download finishes rather than as
|
|
2676
|
+
pieces land. It is distributed and seeded normally in the meantime.
|
|
2677
|
+
</div>`
|
|
2678
|
+
: `<div class="sub" style="margin-bottom:1rem">
|
|
2679
|
+
This is ${escapeHtml(entry.kind ?? 'not a PMTiles')} archive, so it has no tile
|
|
2680
|
+
endpoint β only PMTiles and MBTiles can be served as tiles. It is still
|
|
2681
|
+
distributed and seeded normally.
|
|
2682
|
+
</div>`
|
|
2614
2683
|
}
|
|
2615
2684
|
|
|
2616
2685
|
<h2>Completion hook</h2>
|
|
@@ -2665,7 +2734,7 @@
|
|
|
2665
2734
|
|
|
2666
2735
|
<h2>Actions</h2>
|
|
2667
2736
|
<div class="actions">
|
|
2668
|
-
${
|
|
2737
|
+
${warmable ? '<button id="warm">Warm region</button>' : ''}
|
|
2669
2738
|
<button id="set-location">Set locationβ¦</button>
|
|
2670
2739
|
<button id="clear-cache" ${mode === 'cache' ? '' : 'disabled title="only cache-mode archives have a cache to clear"'}>Clear cache</button>
|
|
2671
2740
|
<button id="recheck" title="Hash the files on disk again and believe the result. For an archive that reads 0% next to a file that is plainly there, or one that claims to be complete and is not β every other figure comes from something written down earlier, and this is the only thing that goes and looks.">Recheck files</button>
|
|
@@ -2895,7 +2964,7 @@
|
|
|
2895
2964
|
}
|
|
2896
2965
|
$('copy-hash').onclick = () => copy(entry.infoHash, 'Infohash');
|
|
2897
2966
|
|
|
2898
|
-
if (
|
|
2967
|
+
if (warmable) {
|
|
2899
2968
|
$('warm').onclick = () => openWarmDialog(entry);
|
|
2900
2969
|
}
|
|
2901
2970
|
|
|
@@ -8126,10 +8195,12 @@ Every piece is hashed against the ` +
|
|
|
8126
8195
|
// missing from a menu the operator is looking at. This is the same
|
|
8127
8196
|
// endpoint the Archives view reads, and it answers a bare array.
|
|
8128
8197
|
const held = await api('/api/torrents');
|
|
8198
|
+
// The same rule the tile route enforces, because a stack source is
|
|
8199
|
+
// read through exactly that path: a complete MBTiles belongs here,
|
|
8200
|
+
// and one still arriving does not -- a stack naming it would answer
|
|
8201
|
+
// 503 for every tile until the download finished.
|
|
8129
8202
|
const free = (held ?? []).filter(
|
|
8130
|
-
(entry) =>
|
|
8131
|
-
!taken.has(entry.infoHash) &&
|
|
8132
|
-
(entry.kind ?? 'pmtiles') === 'pmtiles',
|
|
8203
|
+
(entry) => !taken.has(entry.infoHash) && isServable(entry),
|
|
8133
8204
|
);
|
|
8134
8205
|
if (free.length) {
|
|
8135
8206
|
groups.push(
|