pmtiles-swarm 0.80.0 β 0.90.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/CHANGELOG.md +307 -0
- package/README.md +4 -1
- package/docs/tile-stacks.md +495 -54
- package/package.json +1 -1
- package/src/api.js +332 -34
- package/src/auth.js +4 -0
- package/src/bake-jobs.js +51 -4
- package/src/config.js +47 -0
- package/src/feed.js +9 -3
- package/src/index.js +44 -0
- package/src/library.js +9 -1
- package/src/sources.js +1 -1
- package/src/stack-exports.js +285 -0
- package/src/stack-feed.js +483 -0
- package/src/stack-tile.js +106 -24
- package/src/stacks.js +154 -5
- package/src/tiles.js +109 -1
- package/src/url-sources.js +249 -0
- package/src/web/index.html +535 -21
- package/src/web/public.html +39 -9
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,313 @@
|
|
|
7
7
|
### π Bug fixes
|
|
8
8
|
- _...Add new stuff here..._
|
|
9
9
|
|
|
10
|
+
## 0.90.0
|
|
11
|
+
### β¨ Features and improvements
|
|
12
|
+
- **A stack source may name a URL instead of a category, archive or stack.** `{ "url": "https://β¦" }`,
|
|
13
|
+
read straight over HTTP with no torrent involved β for an archive published as a plain download,
|
|
14
|
+
like Mapterhorn's terrain: a global base plus hundreds of regional patches, 11.8 TiB in total and
|
|
15
|
+
never meant to be downloaded whole. `FetchSource`, from the `pmtiles` package this project already
|
|
16
|
+
depends on, asks for byte ranges the way a swarm-backed source does; a tile costs the header once,
|
|
17
|
+
the directory once, and the tile itself.
|
|
18
|
+
|
|
19
|
+
Parent climbing works the same way it does for a category source β a shallow archive upscales for a
|
|
20
|
+
deeper request through the same code, since reading one is now only a question of which store method
|
|
21
|
+
answers. New per-source `minzoom` and `maxzoom` fields, checked before anything is opened, are what
|
|
22
|
+
make hundreds of these practical: a tile request outside a source's stated box or zoom range skips it
|
|
23
|
+
without a request leaving this node, which for a stack built from a provider's whole file list is
|
|
24
|
+
most of them, on every tile. A URL source always decodes rather than passing through raw, having no
|
|
25
|
+
infohash to answer that question with, and is not seeded, retired or rebuilt β none of the mechanisms
|
|
26
|
+
built for an archive this node actually holds apply to one it does not.
|
|
27
|
+
|
|
28
|
+
- **A provider's list of PMTiles URLs can be imported as sources.** **Stacks β Import URL listβ¦**,
|
|
29
|
+
or `POST /api/stacks/<id>/import`. Mapterhorn's `download_urls.json` names 458 files with the box
|
|
30
|
+
and zoom range of each; naming those by hand is not work anybody should do once, let alone again
|
|
31
|
+
when the provider adds one. An index with an `items` list is read, and so is a plain list of
|
|
32
|
+
addresses for a provider that publishes no index β which shape it is is worked out from the
|
|
33
|
+
document, since somebody pasting an address has no reason to know.
|
|
34
|
+
|
|
35
|
+
The global file becomes `sources[0]` and `required`: a stack is painted bottom-first, so the thing
|
|
36
|
+
covering everywhere has to sit under everything patching it, and the index does not list it first.
|
|
37
|
+
Every other entry keeps its box and zoom range, which is what lets a tile outside one skip it
|
|
38
|
+
without a request leaving the node. The encoding is asked for rather than read β an index rarely
|
|
39
|
+
states it, Mapterhorn's files are all terrarium and its JSON never says so, and a terrain source
|
|
40
|
+
read with the wrong one is a cliff face.
|
|
41
|
+
|
|
42
|
+
The list is fetched **by the node**, not the browser: the console is often on a different network,
|
|
43
|
+
and what matters is that the machine which will read the archives can reach them. **Check** shows
|
|
44
|
+
what an import would write before it writes anything.
|
|
45
|
+
|
|
46
|
+
In the editor an imported batch is one row rather than several hundred cards, with **Re-import**
|
|
47
|
+
and **Remove all**. A re-import replaces only what came from that same address β anything typed by
|
|
48
|
+
hand is left alone β and puts the batch back **where it already was** rather than on the end:
|
|
49
|
+
painting order is the whole meaning of a stack, and a batch that moved each time would quietly bury
|
|
50
|
+
a local override, a day later, on a schedule, with nothing to say why the map had changed.
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
- **A stack can follow a provider's file list on a timer.** A stack feed row with **Into stack** set
|
|
54
|
+
reads a URL list rather than another node's recipes, and keeps the named stack level with it.
|
|
55
|
+
Mapterhorn's index has grown through several versions, and a node that imported it once is a node
|
|
56
|
+
serving whenever that was. The row says which of the two it is by whether **Into stack** is filled
|
|
57
|
+
in β a feed of recipes names its own stacks and an index cannot, being a list of files with no
|
|
58
|
+
opinion about what they are for, so the row supplies the stack and the encoding as well.
|
|
59
|
+
|
|
60
|
+
It reconciles exactly as **Re-import** does: hand-written sources untouched, the batch back where it
|
|
61
|
+
was, a withdrawn file dropped rather than left to 404 per tile. A poll where nothing changed writes
|
|
62
|
+
nothing at all β not the same recipe again, which would move its revision and with it every tile
|
|
63
|
+
cached against it. A stack that does not exist yet is created; one that does keeps everything it had.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
### π Bug fixes
|
|
67
|
+
- **A stack reported no encoding unless its recipe stated one outright.** Reading `output.encoding`
|
|
68
|
+
alone reports null for the ordinary recipe β the one that re-encodes to nothing and writes whatever
|
|
69
|
+
its base source is written in, which is every imported stack, since an import sets the encoding per
|
|
70
|
+
source. Three places read it that way and all three were wrong about terrain: the console offered no
|
|
71
|
+
terrain preview, the TileJSON told clients nothing so terrarium heights rendered through the mapbox
|
|
72
|
+
formula, and a baked archive was written with no encoding metadata at all β an export that had to be
|
|
73
|
+
corrected by hand afterwards to be readable.
|
|
74
|
+
|
|
75
|
+
- **A stack's TileJSON listed every source.** For a stack imported from a provider's index that is 458
|
|
76
|
+
addresses and 55 KB, in a document every map load fetches, describing files a client cannot use and
|
|
77
|
+
will never ask for β it reads tiles from the XYZ endpoint. It now names 25 with a count of the rest.
|
|
78
|
+
The extension it advertises is the one the endpoint actually serves, too: a stack whose sources state
|
|
79
|
+
no format has no coverage format to read, and the document said `.bin` for tiles answered as webp.
|
|
80
|
+
|
|
81
|
+
- **Cancel asked you to fill the form in first.** A `<button>` in a form submits, and a submit is
|
|
82
|
+
checked against the form's required fields before it goes anywhere β so cancelling the import or
|
|
83
|
+
warm dialog answered "Please fill out this field" about a field that was about to be discarded.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## 0.89.0
|
|
87
|
+
### β¨ Features and improvements
|
|
88
|
+
- **Both feeds are linked at the foot of the public page.** `RSS feed` is `archive RSS feed` now and
|
|
89
|
+
`stack RSS feed` is beside it. One name was unambiguous while there was one feed; with a second, a
|
|
90
|
+
reader following the old name would have got archives when they wanted recipes and had nothing on
|
|
91
|
+
the page to tell them otherwise.
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
### π Bug fixes
|
|
95
|
+
- **A feed carrying every category.** `/categories.xml`, beside `/feed.xml` and `/stacks.xml` β the
|
|
96
|
+
set was inconsistent, and following all of a node's categories meant adding each by hand and
|
|
97
|
+
remembering to add the next one, which is not following its categories at all. It is what a
|
|
98
|
+
subscriber wants when they want everything this node files: including categories added later.
|
|
99
|
+
|
|
100
|
+
The items are archives, because a category has no bytes of its own and the build it resolves to is
|
|
101
|
+
what a subscriber would join β which also means every existing consumer already knows how to read
|
|
102
|
+
it, magnets and enclosures included. That is what separates it from the whole catalogue: `/feed.xml`
|
|
103
|
+
carries every build a node holds, and this carries the current one of each category. On a node
|
|
104
|
+
keeping four builds apiece the difference is fourfold.
|
|
105
|
+
|
|
106
|
+
In the footer of the public page it replaces `categories JSON`, which was the odd one out among
|
|
107
|
+
three feeds. `/latest/` is untouched and remains the JSON index.
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
## 0.88.0
|
|
111
|
+
### β¨ Features and improvements
|
|
112
|
+
- **An archive card is built like a category's.** Copy buttons for the addresses that belong
|
|
113
|
+
somewhere else β TileJSON, magnet, and a **source URL** of its own, the TileJSON URL with the
|
|
114
|
+
`.torrent` and magnet in its fragment, pinned to that build rather than following the category.
|
|
115
|
+
The preview, `.torrent` and download stay links, because a page is followed and a file is saved.
|
|
116
|
+
The printed TileJSON row went with the button that replaced it: an address in full beside a button
|
|
117
|
+
that copies it is the same fact twice, and it was the longest line on the card.
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
### π Bug fixes
|
|
121
|
+
- **A terrain stack was offered no hillshade preview on the public page.** The listing reported its
|
|
122
|
+
encoding as whatever `output.encoding` restated, which for a recipe saying "same as the sources" β
|
|
123
|
+
the ordinary case β is nothing. So the page could not tell a terrain stack from an imagery one and
|
|
124
|
+
offered neither the raw preview nor the terrain one. It reports what the stack actually serves now,
|
|
125
|
+
and reports nothing for imagery, where a guess would have offered a hillshade of a photograph.
|
|
126
|
+
|
|
127
|
+
- **A stack whose sources disagreed about their encoding wrote tiles in more than one of them.** With
|
|
128
|
+
no `output.encoding`, the merge took the encoding of whichever source answered first β and which
|
|
129
|
+
source answers varies by tile, since the base is sparse in one place and the layer above covers in
|
|
130
|
+
another. One stack wrote one tile as mapbox and the next as terrarium, with the TileJSON in front
|
|
131
|
+
describing neither: correct in one place, a cliff face in another, for no reason the recipe showed.
|
|
132
|
+
It follows the base source now, which is a property of the recipe rather than of the tile, and the
|
|
133
|
+
listing and the merge are held to the same answer by a test.
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
## 0.87.0
|
|
137
|
+
### β¨ Features and improvements
|
|
138
|
+
- **A feed per stack, and an address to copy for it.** `/stacks/<id>.xml` carries one recipe, for
|
|
139
|
+
following a single map out of somebody's several rather than everything they publish. An **RSS**
|
|
140
|
+
button on the stack's row in the console and beside TileJSON and XYZ on the public page. Copied
|
|
141
|
+
rather than followed: the address is for another node's settings, and a browser shown an RSS
|
|
142
|
+
document mostly offers to download it. A stack this node adopted has no button and its feed 404s β
|
|
143
|
+
somebody else's recipe is theirs to publish.
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
### π Bug fixes
|
|
147
|
+
- **The copied XYZ address came back percent-encoded.** `http://β¦/stacks/test/%7Bz%7D/%7Bx%7D/%7By%7D.png`
|
|
148
|
+
rather than `{z}/{x}/{y}`, which no client will take. The public page resolves a relative address
|
|
149
|
+
against the page's own URL to make it absolute, and `new URL` percent-encodes braces because they
|
|
150
|
+
are not legal in a path β and an XYZ template is very little but braces. The TileJSON link was
|
|
151
|
+
unaffected, having none. Resolving still happens; the two sequences it introduces are put back.
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
## 0.86.0
|
|
155
|
+
### β¨ Features and improvements
|
|
156
|
+
- _...Add new stuff here..._
|
|
157
|
+
|
|
158
|
+
- **Stack recipes travel between nodes.** `GET /stacks.xml` is this node's own stacks as a feed;
|
|
159
|
+
**Settings β Feeds β Stack feeds** follows another node's and adopts what it carries. Archives
|
|
160
|
+
already travelled by category β a builder feeding two tile servers gave them the same archives β
|
|
161
|
+
and this is how the recipes that combine them travel with them, so a stack is written once and
|
|
162
|
+
corrected once.
|
|
163
|
+
|
|
164
|
+
This section of the docs used to argue against a feed, on the grounds that a stack is a mutable
|
|
165
|
+
document and syncing one is about conflicts. That holds where two nodes both edit a recipe and is
|
|
166
|
+
not the arrangement anybody runs: one node authors, the rest follow. What survives from the
|
|
167
|
+
objection is handled directly β **a stack made on this node is never overwritten by one arriving
|
|
168
|
+
under the same name**, which is refused and said.
|
|
169
|
+
|
|
170
|
+
A recipe is adopted under the publisher's own id, so `planet-terrain` answers at the same URL on
|
|
171
|
+
the builder and on every replica; namespacing it would have given three nodes three URLs and
|
|
172
|
+
defeated the point. A recipe naming a source this node has not got is adopted anyway and reports
|
|
173
|
+
the missing source until it arrives β refusing it would mean a replica could not be set up until
|
|
174
|
+
every archive had finished downloading, which is backwards.
|
|
175
|
+
|
|
176
|
+
What happens when a feed stops carrying a stack is the feed's own setting: keep it and say so, or
|
|
177
|
+
remove it here too.
|
|
178
|
+
|
|
179
|
+
### π Bug fixes
|
|
180
|
+
- _...Add new stuff here..._
|
|
181
|
+
|
|
182
|
+
## 0.85.1
|
|
183
|
+
### β¨ Features and improvements
|
|
184
|
+
- _...Add new stuff here..._
|
|
185
|
+
|
|
186
|
+
- **An export no longer pretends a stack has categories.** Both doors fell back to
|
|
187
|
+
`stack.categories` when none were given β a field the typedef never had, validation never checked,
|
|
188
|
+
the editor has no box for and nothing ever wrote. A category is what an *archive* is filed under,
|
|
189
|
+
and a stack has no bytes and no infohash for that to be about.
|
|
190
|
+
|
|
191
|
+
Left empty the archive is unfiled: held and seeded, in no category and no feed. The scheduled
|
|
192
|
+
export row says `unfiled` and the dialog says so in full, rather than offering a default that
|
|
193
|
+
could not exist.
|
|
194
|
+
|
|
195
|
+
### π Bug fixes
|
|
196
|
+
- _...Add new stuff here..._
|
|
197
|
+
|
|
198
|
+
## 0.85.0
|
|
199
|
+
### β¨ Features and improvements
|
|
200
|
+
- _...Add new stuff here..._
|
|
201
|
+
|
|
202
|
+
- **A scheduled export can be served by the node that baked it.** The **Local file** choice, the same
|
|
203
|
+
one every other row under Feeds offers: http, http + web seed, http + catalog. It is worth more
|
|
204
|
+
here than anywhere else β a baked archive is already on this disk, so serving it costs a route
|
|
205
|
+
rather than a download, and without it a scheduled export produces something only peers can reach.
|
|
206
|
+
A nightly build behind a URL that is always current is usually the point of scheduling one.
|
|
207
|
+
|
|
208
|
+
`publishDir` and `webSeedBase` remain the other half of the same question, for a directory
|
|
209
|
+
something else already serves. The two are not exclusive: publishing to a served directory *and*
|
|
210
|
+
offering this node as a web seed gives a client two places to get the same bytes.
|
|
211
|
+
|
|
212
|
+
### π Bug fixes
|
|
213
|
+
- _...Add new stuff here..._
|
|
214
|
+
|
|
215
|
+
## 0.84.0
|
|
216
|
+
### β¨ Features and improvements
|
|
217
|
+
- _...Add new stuff here..._
|
|
218
|
+
|
|
219
|
+
- **Scheduled exports are rows, like every other automation beside them.** `stackExports` in the
|
|
220
|
+
config, edited under Settings β Feeds with the same row editor the monitored folders and the
|
|
221
|
+
scheduled sources use: add a row, choose the stack from a dropdown, say when, and fill in the rest
|
|
222
|
+
β categories, builds to keep, keep for how many days, save location, publish directory, web seed
|
|
223
|
+
base, archive name, attribution, description.
|
|
224
|
+
|
|
225
|
+
**Several rows may name one stack.** That is what the two earlier shapes could not say: an `export`
|
|
226
|
+
block on the recipe, and then a table of one row per stack, both hold exactly one schedule β and a
|
|
227
|
+
nightly build to the fast disk beside a weekly one published elsewhere is an ordinary thing to
|
|
228
|
+
want. It also puts the schedule where the other automations already are: a watched folder says what
|
|
229
|
+
*this machine* does, not what a map is, and keeping it out of the recipe means a recipe copied to
|
|
230
|
+
another node does not quietly start baking there.
|
|
231
|
+
|
|
232
|
+
The export dialog no longer offers to repeat β a stack may have several schedules and a dialog
|
|
233
|
+
opened on the stack cannot say which it would edit. It exports once and points at the settings tab.
|
|
234
|
+
A stack's row in the Stacks view still shows the schedules aimed at it.
|
|
235
|
+
|
|
236
|
+
### π Bug fixes
|
|
237
|
+
- _...Add new stuff here..._
|
|
238
|
+
|
|
239
|
+
## 0.83.0
|
|
240
|
+
### β¨ Features and improvements
|
|
241
|
+
- _...Add new stuff here..._
|
|
242
|
+
|
|
243
|
+
- **A scheduled export is set up like the other automations beside it.** The row under Settings β
|
|
244
|
+
Feeds is the whole of one now, not only the timer: categories, builds to keep, keep for how many
|
|
245
|
+
days, archive name, attribution, description, where the data lands, a publish directory and a web
|
|
246
|
+
seed base. Those are the manual export dialog's fields plus the two retention rules every other
|
|
247
|
+
automation on that tab already had, which is the point β a scheduled export is set up in one place
|
|
248
|
+
rather than half in a settings tab and half in a dialog.
|
|
249
|
+
|
|
250
|
+
Retirement is the part that needed something new underneath. `keep` and `keepDays` are applied by
|
|
251
|
+
the same code a watched folder uses, but retiring needs a *family* β which archives are builds of
|
|
252
|
+
the same map β and a bake marked nothing, so there was nothing to compare. An archive now records
|
|
253
|
+
`source.stack`, and the family is every archive that names this stack. Without it a nightly export
|
|
254
|
+
is a disk that fills at one archive a night.
|
|
255
|
+
|
|
256
|
+
### π Bug fixes
|
|
257
|
+
- _...Add new stuff here..._
|
|
258
|
+
|
|
259
|
+
## 0.82.0
|
|
260
|
+
### β¨ Features and improvements
|
|
261
|
+
- _...Add new stuff here..._
|
|
262
|
+
|
|
263
|
+
- **Export schedules are set under Settings β Feeds.** Not only the two global settings that landed
|
|
264
|
+
there in 0.81.1 β the schedules themselves. **Scheduled exports** is a row per stack: never, every
|
|
265
|
+
day at a time, or every so many hours, saved onto that stack's recipe. Feeds is where somebody goes
|
|
266
|
+
to say when a thing runs, so it is where they are set; the export dialog's **Repeat** control still
|
|
267
|
+
writes the same schedule, for setting one while you are already there.
|
|
268
|
+
|
|
269
|
+
Turning a stack to _never_ pauses it with `enabled: false` rather than deleting the block. Where it
|
|
270
|
+
lands, what it is called and which categories it is filed under live in the same place, and those
|
|
271
|
+
should survive being paused.
|
|
272
|
+
|
|
273
|
+
### π Bug fixes
|
|
274
|
+
- _...Add new stuff here..._
|
|
275
|
+
|
|
276
|
+
## 0.81.1
|
|
277
|
+
### β¨ Features and improvements
|
|
278
|
+
- _...Add new stuff here..._
|
|
279
|
+
|
|
280
|
+
- **The scheduled-export settings are under Settings β Feeds.** `stacks.scheduledExports` and
|
|
281
|
+
`stacks.exportIntervalHours` had no schema entry, so they were config-file-only and invisible in
|
|
282
|
+
the console. Feeds rather than a group of their own, because that tab is already where the
|
|
283
|
+
automations that bring a file in on a timer sit β a scheduled source watching an upstream
|
|
284
|
+
directory, a subscription following someone else's feed. A scheduled export is the same kind of
|
|
285
|
+
thing; it just produces the file here instead of fetching it, and it lands in a category and goes
|
|
286
|
+
out over the feed exactly as a fetched one does.
|
|
287
|
+
|
|
288
|
+
### π Bug fixes
|
|
289
|
+
- _...Add new stuff here..._
|
|
290
|
+
|
|
291
|
+
## 0.81.0
|
|
292
|
+
### β¨ Features and improvements
|
|
293
|
+
- _...Add new stuff here..._
|
|
294
|
+
|
|
295
|
+
- **A stack can export itself on a schedule.** An archive is a snapshot: a stack over categories
|
|
296
|
+
follows a rebuild and a file baked from it does not, so it goes stale the moment its sources move
|
|
297
|
+
and somebody has to notice. An `export` block on the recipe says when β `at` for a time of day in
|
|
298
|
+
UTC, `everyHours` or `everyMinutes` for an interval, the same shape a scheduled source uses and
|
|
299
|
+
read by the same code β along with everything the export dialog collects. In the console, **Repeat**
|
|
300
|
+
turns the Export button into **Save schedule**, and the stack's row shows when it runs.
|
|
301
|
+
|
|
302
|
+
The hard part is remembering across a restart. The source poller keeps last-run times in memory,
|
|
303
|
+
which is fine when a missed poll costs one poll; here it would cost the whole bake, every restart,
|
|
304
|
+
for hours. So it is written to `stack-exports.json`, and written *before* the bake finishes β a
|
|
305
|
+
restart mid-export must not start it from the top, since the checkpoint is what carries it on.
|
|
306
|
+
|
|
307
|
+
A run whose sources have not moved is skipped: `bakeRevision` is recorded beside the time, and an
|
|
308
|
+
identical archive is the same map under a new infohash that then has to be seeded beside the one it
|
|
309
|
+
duplicates. It will not run two at once, will not start one over a bake already running, and does
|
|
310
|
+
not record a refusal as a run β a location that is full is something somebody fixes, and a schedule
|
|
311
|
+
that gave up quietly would hide that it ever ran. `stacks.scheduledExports: false` turns it off,
|
|
312
|
+
which is what a second node serving the same recipes wants.
|
|
313
|
+
|
|
314
|
+
### π Bug fixes
|
|
315
|
+
- _...Add new stuff here..._
|
|
316
|
+
|
|
10
317
|
## 0.80.0
|
|
11
318
|
### β¨ Features and improvements
|
|
12
319
|
- **A stack can be a source in another stack.** `{ "stack": "jaxa-with-gebco" }` beside `category`
|
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ been sending and receiving, kept in SQLite so it survives a restart; an indicato
|
|
|
66
66
|
peers can reach this node at all; and a settings screen covering monitored folders, watched web
|
|
67
67
|
locations, remote nodes, save locations, access tokens and the external-program hooks.
|
|
68
68
|
|
|
69
|
-
**Publishes RSS.** `/feed.xml
|
|
69
|
+
**Publishes RSS.** `/feed.xml` for every archive, `/categories.xml` for the build each category currently resolves to, `/stacks.xml` for the stack recipes, and `/feed/<category>.xml` per category. Plain RSS 2.0 with
|
|
70
70
|
torrent enclosures, so **qBittorrent's built-in RSS auto-downloader can subscribe today** with no
|
|
71
71
|
new software. Items also carry a namespaced description of the map β format, zoom range, bounds,
|
|
72
72
|
tile count β so a subscriber can decide whether it wants a 72 GiB download before starting one.
|
|
@@ -807,12 +807,15 @@ which the endpoint answers 501.
|
|
|
807
807
|
| `GET` | `/api/torrents/:infoHash/stacks` | Which stacks would break if this archive were removed, and how |
|
|
808
808
|
| `GET`, `PUT`, `DELETE` | `/api/stacks/:id/raw`, `/api/stacks/:id` | Read a recipe as written, save one, or remove it. `/raw` is the recipe; `/api/stacks` is what it resolved to |
|
|
809
809
|
|
|
810
|
+
| `POST` | `/api/stacks/:id/import` | Import a provider's list of PMTiles URLs as sources on this stack. An index with an `items` list, or a plain list of addresses; `dryRun` says what it would write without writing it |
|
|
810
811
|
| `POST`, `DELETE` | `/api/stacks/:id/bake` | Run the stack over its sources and write the result as an archive, or stop one that is running. Answers as soon as the job starts; watch it on `/api/stacks` |
|
|
811
812
|
| `GET` | `/stacks/:id/preview` | A map of a stack, for looking at it β **public** |
|
|
812
813
|
| `GET` | `/stacks/:id/tiles.json` | TileJSON for a stack β **public**. `maxzoom` is the maximum over its sources, not the minimum |
|
|
813
814
|
| `GET` | `/stacks/:id/:size/:z/:x/:y.:ext` | The same tile at 256 or 512 px. A tile's coordinates are an extent rather than a pixel count, so this is the same ground on a finer or coarser grid |
|
|
814
815
|
| `GET` | `/stacks/:id/:z/:x/:y.:ext` | One tile of a stack β **public**. Answered by the topmost source holding it; `X-Stack-Sources` says which were asked and what each said |
|
|
815
816
|
| `GET` | `/feed.xml`, `/feed/:category.xml`, `/latest/:category.xml` | RSS β **public** |
|
|
817
|
+
| `GET` | `/categories.xml` | Every category, as the build each resolves to β **public** |
|
|
818
|
+
| `GET` | `/stacks.xml`, `/stacks/:id.xml` | Stack recipes, for another node to follow β **public** |
|
|
816
819
|
|
|
817
820
|
Everything under `/api/` is guarded once a credential is configured; tiles, TileJSON and the feeds
|
|
818
821
|
never are. A `peer` token may read but not change, and may be narrowed to some categories. See
|