tileblaster 0.4.8 → 1.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/UNLICENSE.md +9 -0
- package/bin/tileblaster.js +75 -25
- package/builtins/cache.js +160 -0
- package/builtins/check.js +115 -0
- package/builtins/compress.js +91 -0
- package/builtins/cors.js +33 -0
- package/builtins/deliver.js +34 -0
- package/builtins/dump.js +19 -0
- package/builtins/edit.js +30 -0
- package/builtins/mbtiles.js +52 -0
- package/builtins/modernize.js +57 -0
- package/builtins/noop.js +5 -0
- package/builtins/optimize.js +119 -0
- package/builtins/parse.js +52 -0
- package/builtins/pmtiles.js +80 -0
- package/builtins/sharp.js +46 -0
- package/builtins/tileserver.js +106 -0
- package/builtins/versatiles.js +68 -0
- package/config.dist.js +153 -0
- package/docs/config.md +343 -0
- package/docs/examples.md +257 -0
- package/docs/tileblaster.png +0 -0
- package/docs/tileblaster.svg +261 -0
- package/docs/todo.md +140 -0
- package/lib/debug.js +68 -0
- package/lib/decompress.js +44 -0
- package/lib/load.js +26 -0
- package/lib/mime.js +51 -0
- package/lib/purge.js +109 -0
- package/lib/retrieve.js +15 -0
- package/lib/rfc822date.js +9 -0
- package/lib/router.js +95 -0
- package/lib/store.js +161 -0
- package/lib/strtpl.js +15 -0
- package/lib/tasks.js +50 -0
- package/package.json +25 -13
- package/plugins/example.js +22 -0
- package/readme.md +66 -33
- package/tileblaster.js +445 -0
- package/LICENSE +0 -21
- package/config.js.dist +0 -81
- package/lib/tileblaster.js +0 -787
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
width="150mm"
|
|
6
|
+
height="150mm"
|
|
7
|
+
viewBox="0 50 150 150"
|
|
8
|
+
version="1.1"
|
|
9
|
+
id="svg29401"
|
|
10
|
+
inkscape:version="1.2 (dc2aeda, 2022-05-15)"
|
|
11
|
+
sodipodi:docname="tileblaster.svg"
|
|
12
|
+
inkscape:export-filename="tileblaster.png"
|
|
13
|
+
inkscape:export-xdpi="86.698669"
|
|
14
|
+
inkscape:export-ydpi="86.698669"
|
|
15
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
16
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
17
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
18
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
19
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
20
|
+
<sodipodi:namedview
|
|
21
|
+
id="namedview29403"
|
|
22
|
+
pagecolor="#505050"
|
|
23
|
+
bordercolor="#eeeeee"
|
|
24
|
+
borderopacity="1"
|
|
25
|
+
inkscape:showpageshadow="0"
|
|
26
|
+
inkscape:pageopacity="0"
|
|
27
|
+
inkscape:pagecheckerboard="0"
|
|
28
|
+
inkscape:deskcolor="#505050"
|
|
29
|
+
inkscape:document-units="mm"
|
|
30
|
+
showgrid="false"
|
|
31
|
+
showguides="true"
|
|
32
|
+
inkscape:zoom="1"
|
|
33
|
+
inkscape:cx="382.5"
|
|
34
|
+
inkscape:cy="333.5"
|
|
35
|
+
inkscape:window-width="1859"
|
|
36
|
+
inkscape:window-height="1027"
|
|
37
|
+
inkscape:window-x="61"
|
|
38
|
+
inkscape:window-y="229"
|
|
39
|
+
inkscape:window-maximized="0"
|
|
40
|
+
inkscape:current-layer="layer1">
|
|
41
|
+
<sodipodi:guide
|
|
42
|
+
position="74.999999,38.875"
|
|
43
|
+
orientation="-1,0"
|
|
44
|
+
id="guide32273"
|
|
45
|
+
inkscape:locked="false"
|
|
46
|
+
inkscape:label=""
|
|
47
|
+
inkscape:color="rgb(0,134,229)" />
|
|
48
|
+
<sodipodi:guide
|
|
49
|
+
position="24.694444,74.999999"
|
|
50
|
+
orientation="0,1"
|
|
51
|
+
id="guide34465"
|
|
52
|
+
inkscape:locked="false"
|
|
53
|
+
inkscape:label=""
|
|
54
|
+
inkscape:color="rgb(0,134,229)" />
|
|
55
|
+
<sodipodi:guide
|
|
56
|
+
position="104.51042,150"
|
|
57
|
+
orientation="0,-1"
|
|
58
|
+
id="guide35193"
|
|
59
|
+
inkscape:locked="false" />
|
|
60
|
+
<sodipodi:guide
|
|
61
|
+
position="94.368055,0"
|
|
62
|
+
orientation="0,-1"
|
|
63
|
+
id="guide35195"
|
|
64
|
+
inkscape:locked="false" />
|
|
65
|
+
<sodipodi:guide
|
|
66
|
+
position="0,54.309027"
|
|
67
|
+
orientation="1,0"
|
|
68
|
+
id="guide35197"
|
|
69
|
+
inkscape:locked="false" />
|
|
70
|
+
<sodipodi:guide
|
|
71
|
+
position="150,32.260416"
|
|
72
|
+
orientation="1,0"
|
|
73
|
+
id="guide35199"
|
|
74
|
+
inkscape:locked="false" />
|
|
75
|
+
</sodipodi:namedview>
|
|
76
|
+
<defs
|
|
77
|
+
id="defs29398">
|
|
78
|
+
<linearGradient
|
|
79
|
+
inkscape:collect="always"
|
|
80
|
+
xlink:href="#linearGradient29346-1"
|
|
81
|
+
id="linearGradient31371"
|
|
82
|
+
gradientUnits="userSpaceOnUse"
|
|
83
|
+
gradientTransform="matrix(2.9999997,2.3590334e-8,-2.3590334e-8,2.9999997,-800.00007,-894.07809)"
|
|
84
|
+
x1="400.00006"
|
|
85
|
+
y1="468.68973"
|
|
86
|
+
x2="325.00006"
|
|
87
|
+
y2="425.38846" />
|
|
88
|
+
<linearGradient
|
|
89
|
+
inkscape:collect="always"
|
|
90
|
+
id="linearGradient29346-1">
|
|
91
|
+
<stop
|
|
92
|
+
style="stop-color:#8332ff;stop-opacity:1;"
|
|
93
|
+
offset="0"
|
|
94
|
+
id="stop29342-0" />
|
|
95
|
+
<stop
|
|
96
|
+
style="stop-color:#e816ff;stop-opacity:0.99492383;"
|
|
97
|
+
offset="1"
|
|
98
|
+
id="stop29344-8" />
|
|
99
|
+
</linearGradient>
|
|
100
|
+
<filter
|
|
101
|
+
inkscape:collect="always"
|
|
102
|
+
style="color-interpolation-filters:sRGB"
|
|
103
|
+
id="filter35252"
|
|
104
|
+
x="-0.090126778"
|
|
105
|
+
y="-0.084742466"
|
|
106
|
+
width="1.1802536"
|
|
107
|
+
height="1.1694849">
|
|
108
|
+
<feGaussianBlur
|
|
109
|
+
inkscape:collect="always"
|
|
110
|
+
stdDeviation="3.6361132"
|
|
111
|
+
id="feGaussianBlur35254" />
|
|
112
|
+
</filter>
|
|
113
|
+
<filter
|
|
114
|
+
inkscape:collect="always"
|
|
115
|
+
style="color-interpolation-filters:sRGB"
|
|
116
|
+
id="filter35272"
|
|
117
|
+
x="-0.060782709"
|
|
118
|
+
y="-0.070185916"
|
|
119
|
+
width="1.1215654"
|
|
120
|
+
height="1.1403718">
|
|
121
|
+
<feGaussianBlur
|
|
122
|
+
inkscape:collect="always"
|
|
123
|
+
stdDeviation="11.396758"
|
|
124
|
+
id="feGaussianBlur35274" />
|
|
125
|
+
</filter>
|
|
126
|
+
</defs>
|
|
127
|
+
<g
|
|
128
|
+
inkscape:label="Ebene 1"
|
|
129
|
+
inkscape:groupmode="layer"
|
|
130
|
+
id="layer1"
|
|
131
|
+
transform="translate(179.53655,1.2883869)">
|
|
132
|
+
<g
|
|
133
|
+
id="g35304"
|
|
134
|
+
transform="matrix(1.1361953,0,0,1.1361953,14.238481,-16.847521)">
|
|
135
|
+
<path
|
|
136
|
+
style="fill:#191919;fill-opacity:1;stroke-width:1.17621;stroke-linecap:round"
|
|
137
|
+
d="m -160.68486,91.293103 -1e-5,64.834477 56.14832,32.41724 56.148303,-32.41724 1e-5,-64.834477 -56.148323,-32.417242 z"
|
|
138
|
+
id="path31292" />
|
|
139
|
+
<g
|
|
140
|
+
id="g35262"
|
|
141
|
+
transform="matrix(0.22459324,-0.12966896,0.12966896,0.22459324,-210.22972,70.313386)"
|
|
142
|
+
style="opacity:0.123762;mix-blend-mode:normal;fill:#31e2ff;fill-opacity:1;filter:url(#filter35272)">
|
|
143
|
+
<path
|
|
144
|
+
id="path35256"
|
|
145
|
+
style="fill:#31e2ff;fill-opacity:1;stroke-width:13.6062;stroke-linecap:round"
|
|
146
|
+
d="M 137.49989,187.23365 24.999997,382.08718 137.50003,576.943 l 149.99996,-4e-5 -37.49998,-64.95187 -75.00001,5e-5 -74.99999,-129.90395 37.49998,-64.95114 h 75.00002 l -37.50002,64.95113 74.99999,129.90235 150,10e-6 L 475,382.08718 399.99997,252.18485 H 324.99998 L 362.5,187.23369 287.49999,187.23368 250,252.18485 l -75.00002,10e-6 37.50004,-64.95117 z m 150.00001,129.90234 74.99999,-10e-6 37.5,64.95115 -37.49999,64.95117 -75.00001,-2e-5 -37.49997,-64.95115 z"
|
|
147
|
+
sodipodi:nodetypes="cccccccccccccccccccccccccccc" />
|
|
148
|
+
<path
|
|
149
|
+
id="path35258"
|
|
150
|
+
style="opacity:0.180328;fill:#31e2ff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
151
|
+
d="M 137.5,187.23242 25,382.08789 150,208.88281 212.5,187.23242 Z m 150,0 -37.5,64.95117 50,-43.30078 62.5,-21.64843 z" />
|
|
152
|
+
<path
|
|
153
|
+
id="path35260"
|
|
154
|
+
style="opacity:0.180328;fill:#31e2ff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
155
|
+
d="m 225,295.48438 -87.5,21.65039 h 75 z M 475,382.08789 387.5,490.33984 250,511.99023 H 400 Z M 275,555.29297 137.5,576.94336 h 150 z" />
|
|
156
|
+
</g>
|
|
157
|
+
<path
|
|
158
|
+
id="path29308"
|
|
159
|
+
style="fill:#840577;fill-opacity:0.399267;stroke-width:3.5286;stroke-linecap:round"
|
|
160
|
+
d="m -154.03095,95.1353 -2.6e-4,58.35052 50.53349,29.17555 33.688976,-19.45035 -16.844482,-9.72517 -16.844494,9.72519 -33.689,-19.45038 1e-4,-19.45018 16.8445,-9.72517 -1.1e-4,19.45017 33.688789,19.45003 33.688993,-19.45036 1.86e-4,-38.900359 -33.688797,-19.450003 -16.844481,9.725168 9e-5,-19.450177 -16.8445,9.725176 -8e-5,19.450179 -16.84451,9.725176 1.1e-4,-19.450187 z m 50.53329,9.72484 16.844493,-9.725173 16.844384,9.725003 -8.8e-5,19.45018 -16.844492,9.72516 -16.844397,-9.725 z"
|
|
161
|
+
sodipodi:nodetypes="cccccccccccccccccccccccccccc" />
|
|
162
|
+
<g
|
|
163
|
+
id="g31384"
|
|
164
|
+
transform="matrix(0.22459324,-0.12966896,0.12966896,0.22459324,-210.22972,70.313386)">
|
|
165
|
+
<path
|
|
166
|
+
id="path31363"
|
|
167
|
+
style="fill:url(#linearGradient31371);fill-opacity:1;stroke-width:13.6062;stroke-linecap:round"
|
|
168
|
+
d="M 137.49989,187.23365 24.999997,382.08718 137.50003,576.943 l 149.99996,-4e-5 -37.49998,-64.95187 -75.00001,5e-5 -74.99999,-129.90395 37.49998,-64.95114 h 75.00002 l -37.50002,64.95113 74.99999,129.90235 150,10e-6 L 475,382.08718 399.99997,252.18485 H 324.99998 L 362.5,187.23369 287.49999,187.23368 250,252.18485 l -75.00002,10e-6 37.50004,-64.95117 z m 150.00001,129.90234 74.99999,-10e-6 37.5,64.95115 -37.49999,64.95117 -75.00001,-2e-5 -37.49997,-64.95115 z"
|
|
169
|
+
sodipodi:nodetypes="cccccccccccccccccccccccccccc" />
|
|
170
|
+
<path
|
|
171
|
+
id="path31365"
|
|
172
|
+
style="opacity:0.180328;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
173
|
+
d="M 137.5,187.23242 25,382.08789 150,208.88281 212.5,187.23242 Z m 150,0 -37.5,64.95117 50,-43.30078 62.5,-21.64843 z" />
|
|
174
|
+
<path
|
|
175
|
+
id="path31373"
|
|
176
|
+
style="opacity:0.180328;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
177
|
+
d="m 225,295.48438 -87.5,21.65039 h 75 z M 475,382.08789 387.5,490.33984 250,511.99023 H 400 Z M 275,555.29297 137.5,576.94336 h 150 z" />
|
|
178
|
+
</g>
|
|
179
|
+
<path
|
|
180
|
+
id="path35201"
|
|
181
|
+
style="opacity:0.576733;mix-blend-mode:normal;fill:#010101;fill-opacity:1;stroke-width:0.23538;filter:url(#filter35252)"
|
|
182
|
+
d="m -71.411808,72.221289 -5.095817,2.941939 v 5.884913 l -15.288461,8.826334 h -10.192134 l -5.09633,2.942456 -5.09633,2.942456 -5.09581,2.94194 -8.28994,4.786273 -1.20147,0.6935 -0.70125,0.40462 -25.48062,14.71125 v 17.6537 l 5.09633,2.94246 10.19214,-5.8844 5.09633,2.94194 v 35.30689 l 5.09582,2.94246 20.3848,-11.76879 -5.09633,-2.94246 v -5.8844 -23.53809 l 10.19266,-5.8844 v -5.88439 -5.2e-4 l 5.095807,-2.94194 v -5.8844 l 5.096327,-2.94245 v -5.8844 l 35.672739,-20.595639 -5.096327,-2.942456 v -5.884396 l -5.095807,2.941939 z"
|
|
183
|
+
transform="matrix(0.98017487,0,0,0.98017487,-2.0724487,2.4525763)" />
|
|
184
|
+
<g
|
|
185
|
+
id="g29366"
|
|
186
|
+
transform="matrix(0.19980409,-0.11535694,0.11535694,0.19980409,-191.07133,74.765286)">
|
|
187
|
+
<path
|
|
188
|
+
style="fill:#949fab;fill-opacity:1"
|
|
189
|
+
d="m 75.000005,338.78592 12.499997,21.65063 -75,129.90381 12.500003,21.65064 H 125.00001 L 112.5,490.34036 200,338.78592 Z"
|
|
190
|
+
id="path25198"
|
|
191
|
+
sodipodi:nodetypes="cccccccc" />
|
|
192
|
+
<path
|
|
193
|
+
style="fill:#e6e9ed;fill-opacity:1;stroke-width:4.53543;stroke-linecap:round"
|
|
194
|
+
d="M 12.499997,317.13529 50,252.18338 h 250 l 37.5,21.65064 -37.5,64.9519 H 25.000006 Z"
|
|
195
|
+
id="path25379"
|
|
196
|
+
sodipodi:nodetypes="ccccccc" />
|
|
197
|
+
<path
|
|
198
|
+
style="fill:#ed5564;fill-opacity:1;stroke-width:4.53543;stroke-linecap:round"
|
|
199
|
+
d="m 187.5,360.43655 h 50 L 225,382.08719 h -50 z"
|
|
200
|
+
id="path25444"
|
|
201
|
+
sodipodi:nodetypes="ccccc" />
|
|
202
|
+
<path
|
|
203
|
+
style="fill:#8994a2;fill-opacity:1;stroke-width:4.53543;stroke-linecap:round"
|
|
204
|
+
d="M 300,252.18338 275,295.48465 262.5,273.83402 275,252.18338 H 250 L 225,295.48465 213.13802,274.9391 225,252.18338 h -25 l -25,43.30127 -12.35149,-21.39341 12.3515,-21.90786 H 275 Z"
|
|
205
|
+
id="path25509"
|
|
206
|
+
sodipodi:nodetypes="cccccccccccccc" />
|
|
207
|
+
<path
|
|
208
|
+
style="fill:#949fab;fill-opacity:1;stroke-width:4.53543;stroke-linecap:round"
|
|
209
|
+
d="m 337.5,273.83401 -12.5,21.65064 -12.5,21.65064 175,-10e-6 -12.5,-21.65063 12.5,-21.65063 z"
|
|
210
|
+
id="path26345"
|
|
211
|
+
sodipodi:nodetypes="ccccccc" />
|
|
212
|
+
<path
|
|
213
|
+
style="fill:#8994a2;fill-opacity:1;stroke-width:4.53543;stroke-linecap:round"
|
|
214
|
+
d="m 412.49999,273.83402 12.5,-21.65064 H 450 l 12.5,21.65064 h -50.00001"
|
|
215
|
+
id="path26420" />
|
|
216
|
+
<path
|
|
217
|
+
style="fill:#8994a2;fill-opacity:1;stroke-width:4.53543;stroke-linecap:round"
|
|
218
|
+
d="m 200,338.78591 75,10e-6 -12.50001,21.65063 H 187.5 Z"
|
|
219
|
+
id="path26432"
|
|
220
|
+
sodipodi:nodetypes="ccccc" />
|
|
221
|
+
<path
|
|
222
|
+
style="fill:#ffffff;fill-opacity:0.0967742;stroke-width:4.53543;stroke-linecap:round"
|
|
223
|
+
d="M 12.499997,317.13529 50,252.18338 H 300 L 62.500003,273.83402 Z"
|
|
224
|
+
id="path26937" />
|
|
225
|
+
<path
|
|
226
|
+
style="fill:#000000;fill-opacity:0.0967742;stroke-width:4.53543;stroke-linecap:round"
|
|
227
|
+
d="M 112.5,490.34036 99.999998,468.68973 175,338.78592 h 100 l -87.5,21.65063 z"
|
|
228
|
+
id="path28766" />
|
|
229
|
+
<path
|
|
230
|
+
style="fill:#ffffff;fill-opacity:0.0967742;stroke-width:4.53543;stroke-linecap:round"
|
|
231
|
+
d="m 325,295.48465 12.5,-21.65063 h 150 z"
|
|
232
|
+
id="path28831" />
|
|
233
|
+
<path
|
|
234
|
+
style="fill:#000000;fill-opacity:0.0967742;stroke-width:4.53543;stroke-linecap:round"
|
|
235
|
+
d="M 312.5,317.13529 475,295.48465 487.49999,317.13529 Z"
|
|
236
|
+
id="path28833" />
|
|
237
|
+
<path
|
|
238
|
+
style="fill:#000000;fill-opacity:0.0967742;stroke-width:4.53543;stroke-linecap:round"
|
|
239
|
+
d="M 337.5,273.83401 275,338.78592 h 25 z"
|
|
240
|
+
id="path28835" />
|
|
241
|
+
<path
|
|
242
|
+
style="fill:#ffffff;fill-opacity:0.0967742;stroke-width:4.53543;stroke-linecap:round"
|
|
243
|
+
d="M 87.500002,360.43655 25.000006,511.991 12.500002,490.34036 Z"
|
|
244
|
+
id="path28837"
|
|
245
|
+
sodipodi:nodetypes="cccc" />
|
|
246
|
+
<path
|
|
247
|
+
style="fill:#000000;fill-opacity:0.131086;stroke-width:4.53543;stroke-linecap:round"
|
|
248
|
+
d="m 175,382.08719 h -25 l 12.5,21.65063 h -25 l 12.5,21.65064 h -25 l 12.5,21.65063 h -25 l 12.5,21.65064 z"
|
|
249
|
+
id="path28914" />
|
|
250
|
+
<path
|
|
251
|
+
style="fill:#000000;fill-opacity:0.131086;stroke-width:4.53543;stroke-linecap:round"
|
|
252
|
+
d="m 175,382.08719 12.5,-21.65064 h 50 z"
|
|
253
|
+
id="path28979" />
|
|
254
|
+
<path
|
|
255
|
+
style="fill:#ffffff;fill-opacity:0.131086;stroke-width:4.53543;stroke-linecap:round"
|
|
256
|
+
d="m 412.5,273.83402 12.49999,-21.65064 H 450 Z"
|
|
257
|
+
id="path28981" />
|
|
258
|
+
</g>
|
|
259
|
+
</g>
|
|
260
|
+
</g>
|
|
261
|
+
</svg>
|
package/docs/todo.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Todo
|
|
2
|
+
|
|
3
|
+
## Roadmap
|
|
4
|
+
|
|
5
|
+
### 1.0 Release
|
|
6
|
+
|
|
7
|
+
* [x] Config format
|
|
8
|
+
* [x] Map format
|
|
9
|
+
* [x] Tasks fomat
|
|
10
|
+
* [x] HTTP Server, Port and Socket
|
|
11
|
+
* [x] Graceful shutdown
|
|
12
|
+
* [x] Debug Library → `lib/debug.js`
|
|
13
|
+
* [x] Optional Module Loader → `lib/load.js`
|
|
14
|
+
* [x] HTTPs Abstraction (~got or~ phin) → `lib/retrieve.js`
|
|
15
|
+
* [x] Plugin Interface / Task Runner
|
|
16
|
+
* [x] Builtins
|
|
17
|
+
* [x] CORS
|
|
18
|
+
* [x] Parse Request
|
|
19
|
+
* [x] Check Request
|
|
20
|
+
* [x] Tile Backends
|
|
21
|
+
* [x] ZXY Webtiles → `builtin/tileserver.js`
|
|
22
|
+
* [x] TMS Webtiles → `builtin/tileserver.js`
|
|
23
|
+
* [x] Versatiles
|
|
24
|
+
* [x] PMTiles
|
|
25
|
+
* [x] MBTiles
|
|
26
|
+
* [x] Optimization (optipng, mozjpeg, svgo?, pbfcrop?)
|
|
27
|
+
* [x] Modernize Raster Formats (png,jpeg → webp,avif)
|
|
28
|
+
* [x] Caching to Disk
|
|
29
|
+
* [x] Reading cached tile from Disk
|
|
30
|
+
* [x] Skipping Jobs
|
|
31
|
+
* [x] Etag Headers
|
|
32
|
+
* [x] Last-Modified Headers
|
|
33
|
+
* [x] Don't store if expired
|
|
34
|
+
* [x] Expires Headers
|
|
35
|
+
* [x] Don't update if already cached (in case of store-only)
|
|
36
|
+
* [x] ~Cache-Control Headers~ → Set via `deliver` builtin
|
|
37
|
+
* [x] Delivery
|
|
38
|
+
* [x] Debug Dump
|
|
39
|
+
* [x] Vectortile Editing
|
|
40
|
+
* [x] Full image manipulation for raster tiles → https://www.npmjs.com/package/sharp
|
|
41
|
+
* [x] Vectortiles Editor → https://www.npmjs.com/package/vtt
|
|
42
|
+
* [x] Cache Cleaning Worker
|
|
43
|
+
* [x] Documentation
|
|
44
|
+
* [x] What is Tileblaster, what is the benefit for the user
|
|
45
|
+
* [x] What can't tileblaster do
|
|
46
|
+
* [x] All config options
|
|
47
|
+
* [x] All builtins
|
|
48
|
+
* [x] Example Config
|
|
49
|
+
* [x] Example Nginx Config
|
|
50
|
+
* [x] How to use it, Standalone or behind Proxy
|
|
51
|
+
* [x] Core concepts explained (maps, work queue, builtins and plugins)
|
|
52
|
+
* [x] Examples
|
|
53
|
+
* [x] Caching proxy for a tileserver
|
|
54
|
+
* [x] Serve tiles from container
|
|
55
|
+
* [x] Raster editing: "Dark mode"
|
|
56
|
+
* [x] Vector editing: remove unused layers
|
|
57
|
+
* How to contribute, bug reports
|
|
58
|
+
* [x] CLI
|
|
59
|
+
* [x] Cluster Support
|
|
60
|
+
* [x] PM2 Integration
|
|
61
|
+
* [x] Rudimentary Dev Server
|
|
62
|
+
* [x] Request Queue to throttle unfulfilled requests
|
|
63
|
+
* [x] Fancy Default Page
|
|
64
|
+
* [x] Custom String Template function for {x} replacement instead of regex
|
|
65
|
+
|
|
66
|
+
### Next
|
|
67
|
+
|
|
68
|
+
* [ ] Redirects
|
|
69
|
+
* [ ] Convert Geojson ↔ Topojson
|
|
70
|
+
* [ ] Map Web Interface, Configurable
|
|
71
|
+
* [ ] Configurable Index Page
|
|
72
|
+
* [ ] Support for Glyphs and Styles, tile.json proxy
|
|
73
|
+
* [ ] Better Error Handling
|
|
74
|
+
* [ ] Error wrapper (to pass along http status etc)?
|
|
75
|
+
* [ ] 404 for nonexistant tiles
|
|
76
|
+
* [ ] Render Vector Tiles with MapLibreGL-Native
|
|
77
|
+
* [ ] Improve Debug Consistency
|
|
78
|
+
* [ ] Documentation: How to write a plugin
|
|
79
|
+
|
|
80
|
+
### Later
|
|
81
|
+
|
|
82
|
+
* [ ] Screencast
|
|
83
|
+
* [ ] Monitoring / Status / Statistics Interface
|
|
84
|
+
* [ ] Integration with Nginx-Cache
|
|
85
|
+
* [ ] Memcache → https://www.npmjs.com/package/iomem
|
|
86
|
+
* [ ] Backends
|
|
87
|
+
[ ] tilebase https://www.npmjs.com/package/tilebase
|
|
88
|
+
[ ] Geotiff?
|
|
89
|
+
[ ] PostGIS database via ST_AsMVT?
|
|
90
|
+
* [ ] Conversions
|
|
91
|
+
* [ ] pbf → svg
|
|
92
|
+
* [ ] svg → raster
|
|
93
|
+
* [ ] geotif → raster
|
|
94
|
+
|
|
95
|
+
### Probably Never
|
|
96
|
+
|
|
97
|
+
* [ ] v0 Config Migration?
|
|
98
|
+
* [ ] use mbtiles database as cache?
|
|
99
|
+
* [ ] Standalone Logging?
|
|
100
|
+
* [ ] Config Web Interface
|
|
101
|
+
* [ ] Standalone Daemon with pid files?
|
|
102
|
+
* [ ] Cache: Store in MBTiles or similar?
|
|
103
|
+
* [ ] GDAL?
|
|
104
|
+
* [ ] Footprint
|
|
105
|
+
* [ ] Replace Phin?
|
|
106
|
+
* [ ] ~Nginx Cache Hydration~ (Problem: different file owners)
|
|
107
|
+
|
|
108
|
+
## Format Support
|
|
109
|
+
|
|
110
|
+
* [x] Vector
|
|
111
|
+
* [x] mvt/pbf
|
|
112
|
+
* [ ] svg
|
|
113
|
+
* [x] Raster
|
|
114
|
+
* [x] png
|
|
115
|
+
* [x] jpeg
|
|
116
|
+
* [x] webp
|
|
117
|
+
* [x] avif
|
|
118
|
+
* [ ] geotif (readonly)
|
|
119
|
+
* [ ] Data
|
|
120
|
+
* [ ] GeoJSON
|
|
121
|
+
* [ ] TopoJSON
|
|
122
|
+
* [ ] JSON
|
|
123
|
+
* [ ] ArcJSON?
|
|
124
|
+
* [ ] WKT? → https://en.wikipedia.org/w/index.php?title=Well-known_text_representation_of_geometry
|
|
125
|
+
|
|
126
|
+
## Conversions
|
|
127
|
+
|
|
128
|
+
* [ ] GeoJSON ↔ TopoJSON
|
|
129
|
+
* [ ] WKT → GeoJSON TopoJSON
|
|
130
|
+
* [ ] GeoJSON TopoJSON → SVG
|
|
131
|
+
* [ ] PNG JPEG WEBP AVIF TIF SVG → PNG JPEG WEBP AVIF
|
|
132
|
+
* [ ] MVT → SVG
|
|
133
|
+
* [ ] MVT → GeoJSON TopoJSON
|
|
134
|
+
|
|
135
|
+
## Etag
|
|
136
|
+
|
|
137
|
+
``` js
|
|
138
|
+
// nginx etag — for consistency
|
|
139
|
+
etag = util.format('"%s-%s"', Math.floor(mtimeMs/1000).toString(16), filesize.toString(16));
|
|
140
|
+
```
|
package/lib/debug.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
|
|
2
|
+
// placeholder debug module
|
|
3
|
+
|
|
4
|
+
const colrz = require("colrz");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
const format = require("node:util").format;
|
|
7
|
+
|
|
8
|
+
// enabled if env.DEBUG has tileblaster or *
|
|
9
|
+
const enabled = (process.env.DEBUG && process.env.DEBUG.split(/, ?/).find(function(debug){ return debug === "*" || debug.slice(0,11) === "tileblaster"; }) && true);
|
|
10
|
+
|
|
11
|
+
// time between outputs helper
|
|
12
|
+
let time = Date.now();
|
|
13
|
+
function since(){
|
|
14
|
+
let since = Date.now()-time;
|
|
15
|
+
time = Date.now();
|
|
16
|
+
if (since > 300000) return "+"+Math.round(since/60000)+"m";
|
|
17
|
+
if (since > 1000) return "+"+(since/1000).toFixed(1)+"s";
|
|
18
|
+
return "+"+since.toFixed(0)+"ms";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function prefix(){
|
|
22
|
+
if (!process.env.workerid) return "";
|
|
23
|
+
return format("#%s".magenta+" | ".grey, process.env.workerid.magenta);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// default: just print with since
|
|
27
|
+
module.exports = function(){
|
|
28
|
+
if (enabled) console.error(prefix()+"%s %s", format(...arguments), since());
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// warnings with a yellow label
|
|
32
|
+
module.exports.warn = function(){
|
|
33
|
+
if (enabled) console.error(prefix()+"Warning:".yellow+" %s %s", format(...arguments), since().brightYellow);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// info with a blue label
|
|
37
|
+
module.exports.info = function(){
|
|
38
|
+
if (enabled) console.error(prefix()+"Info:".cyan+" %s %s", format(...arguments), since().brightBlue);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// errors with a red label and fancy printing of Error instances FIXME refactor
|
|
42
|
+
module.exports.error = function(){
|
|
43
|
+
if (!enabled) return;
|
|
44
|
+
|
|
45
|
+
let stacks = [];
|
|
46
|
+
arguments = Array.from(arguments).map(function(arg){
|
|
47
|
+
if (arg instanceof Error) {
|
|
48
|
+
if (arg.stack) stacks.push(arg.stack);
|
|
49
|
+
return arg.message;
|
|
50
|
+
}
|
|
51
|
+
return arg;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
console.error(prefix()+"Error:".red+" %s %s", format(...arguments), since().brightRed);
|
|
55
|
+
|
|
56
|
+
// format and prettify stack (a little overkill)
|
|
57
|
+
stacks.forEach(function(stack){
|
|
58
|
+
const lines = stack.split("\n").slice(1);
|
|
59
|
+
if (lines.length === 0) return;
|
|
60
|
+
console.error("┏┉┉┉ ".brightRed+"Stack".red+" ┉┉┉".brightRed);
|
|
61
|
+
console.error("┋".brightRed);
|
|
62
|
+
lines.forEach(function(line){
|
|
63
|
+
console.error("┋".brightRed+" %s", line.trim());
|
|
64
|
+
});
|
|
65
|
+
console.error("┋".brightRed);
|
|
66
|
+
console.error("┗┉┉┉".brightRed);
|
|
67
|
+
});
|
|
68
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const load = require("../lib/load");
|
|
2
|
+
const zlib = require("node:zlib");
|
|
3
|
+
const lzma = load("node-liblzma");
|
|
4
|
+
const zstd = load("fzstd");
|
|
5
|
+
|
|
6
|
+
const decompress = module.exports = function decompress(buf, compression, fn){
|
|
7
|
+
|
|
8
|
+
// promisify
|
|
9
|
+
if (!fn || typeof fn !== "function") return new Promise(function(resolve, reject){
|
|
10
|
+
decompress(buf, compression, function(err, buf){
|
|
11
|
+
if (err) return reject(err);
|
|
12
|
+
return resolve(buf);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
switch (compression) {
|
|
17
|
+
case "gzip":
|
|
18
|
+
case "gz":
|
|
19
|
+
zlib.gunzip(buf, fn);
|
|
20
|
+
break;
|
|
21
|
+
case "brotli":
|
|
22
|
+
case "br":
|
|
23
|
+
zlib.brotliDecompress(buf, fn);
|
|
24
|
+
break;
|
|
25
|
+
case "inflate":
|
|
26
|
+
case "deflate":
|
|
27
|
+
zlib.inflate(buf, fn);
|
|
28
|
+
break;
|
|
29
|
+
case "lzma":
|
|
30
|
+
case "xz":
|
|
31
|
+
if (!lzma) return fn(new Error("Missing optional dependency: 'node-liblzma'"));
|
|
32
|
+
lzma.unxz(buf, fn);
|
|
33
|
+
break;
|
|
34
|
+
case "zstd":
|
|
35
|
+
if (!zstd) return fn(new Error("Missing optional dependency: 'fzstd'"));
|
|
36
|
+
try {
|
|
37
|
+
fn(null, fzstd.decompress(buf));
|
|
38
|
+
} catch (err) {
|
|
39
|
+
fn(err);
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
default: return fn(null, buf); // pass through if unknown
|
|
43
|
+
}
|
|
44
|
+
};
|
package/lib/load.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
|
|
2
|
+
// require wrapper that doesn't throw errors
|
|
3
|
+
const load = function load(r){
|
|
4
|
+
return (r && typeof r === "string" && (load.has(r) || load.exists(r))) ? require(r) : undefined;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// cache
|
|
8
|
+
load.modules = {};
|
|
9
|
+
|
|
10
|
+
// check if module is known
|
|
11
|
+
load.has = function(r){
|
|
12
|
+
return load.modules.hasOwnProperty(r) ? load.modules[r] : false;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// check if module exists
|
|
16
|
+
load.exists = function(r){
|
|
17
|
+
try {
|
|
18
|
+
require.resolve(r);
|
|
19
|
+
} catch(err) {
|
|
20
|
+
return load.modules[r] = false;
|
|
21
|
+
}
|
|
22
|
+
return load.modules[r] = true;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// export
|
|
26
|
+
module.exports = load;
|
package/lib/mime.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// file types and mime types
|
|
2
|
+
|
|
3
|
+
// look up mime type for extension
|
|
4
|
+
module.exports.mimetype = function(ext, dflt){
|
|
5
|
+
return mimetypes[ext] && mimetypes[ext][0] || dflt || "application/octet-stream";
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// look up file type for mime type
|
|
9
|
+
module.exports.filetype = function(mimetype, dflt){
|
|
10
|
+
return filetypes[mimetype] && filetypes[mimetype][0] || dflt || "bin";
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const mimetypes = {
|
|
14
|
+
|
|
15
|
+
// dflt unknown
|
|
16
|
+
bin: [ "application/octet-stream" ],
|
|
17
|
+
|
|
18
|
+
// raster
|
|
19
|
+
png: [ "image/png" ],
|
|
20
|
+
jpg: [ "image/jpeg" ],
|
|
21
|
+
jpeg: [ "image/jpeg" ],
|
|
22
|
+
gif: [ "image/gif" ],
|
|
23
|
+
webp: [ "image/webp" ],
|
|
24
|
+
avif: [ "image/aviv" ],
|
|
25
|
+
tif: [ "image/tiff" ],
|
|
26
|
+
tiff: [ "image/tiff" ],
|
|
27
|
+
|
|
28
|
+
// vector
|
|
29
|
+
svg: [ "image/svg+xml", "image/svg" ],
|
|
30
|
+
mvt: [ "application/vnd.mapbox-vector-tile", "application/x-protobuf", "application/protobuf", "application/vnd.google.protobuf", "application/octet-stream" ],
|
|
31
|
+
pbf: [ "application/x-protobuf", "application/protobuf", "application/vnd.google.protobuf", "application/octet-stream" ],
|
|
32
|
+
|
|
33
|
+
// data
|
|
34
|
+
json: [ "application/json", "text/json" ],
|
|
35
|
+
geojson: [ "application/geo+json", "application/json", "text/json" ],
|
|
36
|
+
topojson: [ "application/topo+json", "application/json", "text/json" ],
|
|
37
|
+
|
|
38
|
+
// containers
|
|
39
|
+
versatiles: [ "application/x-versatiles", "application/vnd.versatiles", "application/octet-stream" ],
|
|
40
|
+
cloudtiles: [ "application/x-cloudtiles", "application/vnd.cloudtiles", "application/octet-stream" ],
|
|
41
|
+
pmtiles: [ "application/x-pmtiles", "application/vnd.pmtiles", "application/octet-stream" ],
|
|
42
|
+
mbtiles: [ "application/vnd.sqlite3", "application/x-sqlite3", "application/sqlite3", "application/vnd.mbtiles", "application/x-mbtiles", "application/mbtiles", "application/octet-stream" ],
|
|
43
|
+
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const filetypes = Object.entries(mimetypes).reduce(function(lookup, [ extension, types ]){
|
|
47
|
+
types.forEach(function(type){
|
|
48
|
+
lookup[type] = [ ...(lookup[type]||[]), extension ];
|
|
49
|
+
});
|
|
50
|
+
return lookup;
|
|
51
|
+
},{});
|