chiitiler 1.14.2 → 1.15.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/README.md +47 -2
- package/dist/cache/gcs.d.ts +10 -0
- package/dist/cache/gcs.js +66 -0
- package/dist/cache/index.d.ts +2 -1
- package/dist/cache/index.js +2 -1
- package/dist/cli.js +26 -0
- package/dist/gcs.d.ts +7 -0
- package/dist/gcs.js +14 -0
- package/dist/source/gcs.d.ts +2 -0
- package/dist/source/gcs.js +21 -0
- package/dist/source/index.js +3 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ you can pass server options via environment variables
|
|
|
99
99
|
| CHIITILER_PROCESSES | 1 | num of chiitiler processes. 0 means all-CPUs |
|
|
100
100
|
| CHIITILER_DEBUG | false | debug mode |
|
|
101
101
|
| CHIITILER_STREAM_MODE | false | stream mode |
|
|
102
|
-
| CHIITILER_CACHE_METHOD | none | cache method, `none`, `memory`, `file` or `
|
|
102
|
+
| CHIITILER_CACHE_METHOD | none | cache method, `none`, `memory`, `file`, `s3` or `gcs` |
|
|
103
103
|
| CHIITILER_CACHE_TTL_SEC | 3600 | cache ttl, effect to `memory` and `file` |
|
|
104
104
|
| CHIITILER_MEMORYCACHE_MAXITEMCOUNT | 1000 | max items for memorycache |
|
|
105
105
|
| CHIITILER_FILECACHE_DIR | .cache | filecache directory |
|
|
@@ -107,6 +107,11 @@ you can pass server options via environment variables
|
|
|
107
107
|
| CHIITILER_S3_REGION | us-east1 | s3 bucket region for caching/fetching |
|
|
108
108
|
| CHIITILER_S3_ENDPOINT | | s3 endpoint for caching/fetching |
|
|
109
109
|
| CHIITILER_S3_FORCE_PATH_STYLE | false | force path style for s3, needed for minio |
|
|
110
|
+
| CHIITILER_GCS_CACHE_BUCKE | | gcs cache bucket name |
|
|
111
|
+
| CHIITILER_GCS_CACHE_PREFIX | | gcs cache prefix |
|
|
112
|
+
| CHIITILER_GCS_PROJECT_ID | | gcs project id |
|
|
113
|
+
| CHIITILER_GCS_KEY_FILENAME | | gcs key filename |
|
|
114
|
+
| CHIITILER_GCS_API_ENDPOINT | | gcs api endpoint |
|
|
110
115
|
|
|
111
116
|
### debug page
|
|
112
117
|
|
|
@@ -115,11 +120,18 @@ you can pass server options via environment variables
|
|
|
115
120
|
- You can pass style.json url: <http://localhost:3000/debug?url=https://tile.openstreetmap.jp/styles/osm-bright/style.json>
|
|
116
121
|
- editor page: <http://localhost:3000/editor>
|
|
117
122
|
|
|
123
|
+
## deployment
|
|
124
|
+
|
|
125
|
+
### AWS CDK
|
|
126
|
+
|
|
127
|
+
- you can deploy chiitiler with AWS CDK, check [cdk](./cdk)
|
|
128
|
+
|
|
118
129
|
## supported protocols in style.json
|
|
119
130
|
|
|
120
131
|
- `http://` or `https://` protocol are used in Style Specification
|
|
121
132
|
- In addition, chiitiler supports following protocols:
|
|
122
133
|
- `s3://` for S3 bucket
|
|
134
|
+
- `gs://` for Google Cloud Storage bucket
|
|
123
135
|
- `file://` for file system
|
|
124
136
|
- `mbtiles://` for MBTIles files
|
|
125
137
|
- `pmtiles://` for PMTiles, remote or local or s3
|
|
@@ -162,6 +174,13 @@ you can pass server options via environment variables
|
|
|
162
174
|
],
|
|
163
175
|
"maxzoom": 6
|
|
164
176
|
},
|
|
177
|
+
"gcs": {
|
|
178
|
+
"type": "vector",
|
|
179
|
+
"tiles": [
|
|
180
|
+
"gs://tiles/{z}/{x}/{y}.pbf"
|
|
181
|
+
],
|
|
182
|
+
"maxzoom": 6
|
|
183
|
+
},
|
|
165
184
|
"cog": {
|
|
166
185
|
"type": "raster",
|
|
167
186
|
"tiles": [
|
|
@@ -211,6 +230,26 @@ you can pass server options via environment variables
|
|
|
211
230
|
"circle-color": "green"
|
|
212
231
|
}
|
|
213
232
|
},
|
|
233
|
+
{
|
|
234
|
+
"id": "pmtiles-s3",
|
|
235
|
+
"source": "pmtiles-s3",
|
|
236
|
+
"source-layer": "P2921",
|
|
237
|
+
"type": "circle",
|
|
238
|
+
"paint": {
|
|
239
|
+
"circle-radius": 3,
|
|
240
|
+
"circle-color": "purple"
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"id": "gcs",
|
|
245
|
+
"source": "gcs",
|
|
246
|
+
"source-layer": "P2921",
|
|
247
|
+
"type": "circle",
|
|
248
|
+
"paint": {
|
|
249
|
+
"circle-radius": 3,
|
|
250
|
+
"circle-color": "purple"
|
|
251
|
+
}
|
|
252
|
+
},
|
|
214
253
|
{
|
|
215
254
|
"id": "cog",
|
|
216
255
|
"source": "cog",
|
|
@@ -252,6 +291,11 @@ const s3Cache = ChiitilerCache.s3Cache({
|
|
|
252
291
|
});
|
|
253
292
|
// credentials are loaded from environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
|
|
254
293
|
|
|
294
|
+
const gcsCache = ChiitilerCache.gcsCache({
|
|
295
|
+
bucket: 'chiitiler',
|
|
296
|
+
});
|
|
297
|
+
// credentials are loaded from environment variables: GOOGLE_APPLICATION_CREDENTIALS
|
|
298
|
+
|
|
255
299
|
const tileBuf = await getRenderedTileBuffer({
|
|
256
300
|
stylejson: 'https://example.com/style.json', // or StyleSpecification object
|
|
257
301
|
z: 0,
|
|
@@ -278,4 +322,5 @@ const bboxBuf = await getRenderedBboxBuffer({
|
|
|
278
322
|
|
|
279
323
|
## development
|
|
280
324
|
|
|
281
|
-
- run `docker compose up`
|
|
325
|
+
- To debug S3, run `docker compose up`
|
|
326
|
+
- To debug GCS, change `CHIITILER_CACHE_METHOD` to `gcs` in `docker-compose.yml`, and then run `docker compose up`
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Cache } from './index.js';
|
|
2
|
+
type GCSCacheOptions = {
|
|
3
|
+
bucket: string;
|
|
4
|
+
prefix?: string;
|
|
5
|
+
projectId?: string;
|
|
6
|
+
keyFilename?: string;
|
|
7
|
+
apiEndpoint?: string;
|
|
8
|
+
};
|
|
9
|
+
declare function gcsCache(options: GCSCacheOptions): Cache;
|
|
10
|
+
export { gcsCache };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { getStorageClient } from '../gcs.js';
|
|
2
|
+
function gcsCache(options) {
|
|
3
|
+
if (options.prefix?.endsWith('/')) {
|
|
4
|
+
options.prefix = options.prefix.slice(0, -1);
|
|
5
|
+
}
|
|
6
|
+
const storageClient = getStorageClient({
|
|
7
|
+
projectId: options.projectId,
|
|
8
|
+
keyFilename: options.keyFilename,
|
|
9
|
+
apiEndpoint: options.apiEndpoint,
|
|
10
|
+
});
|
|
11
|
+
const bucket = storageClient.bucket(options.bucket);
|
|
12
|
+
function bucketFile(key) {
|
|
13
|
+
const name = escapeFileName(key);
|
|
14
|
+
const nameWithPrefix = options.prefix ? `${options.prefix}/${name}` : name;
|
|
15
|
+
return bucket.file(nameWithPrefix);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
name: 'gcs',
|
|
19
|
+
set: async function (key, value) {
|
|
20
|
+
const file = bucketFile(key);
|
|
21
|
+
try {
|
|
22
|
+
await file.save(value, {
|
|
23
|
+
resumable: false,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
console.log(`[error]: ${e}`);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
get: async function (key) {
|
|
31
|
+
const file = bucketFile(key);
|
|
32
|
+
try {
|
|
33
|
+
const [content] = await file.download();
|
|
34
|
+
return Buffer.from(content);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// miss or any error
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function escapeFileName(url) {
|
|
44
|
+
return url
|
|
45
|
+
.replace(/\//g, '_') // replace slashes with underscores
|
|
46
|
+
.replace(/\?/g, '-') // replace question marks with dashes
|
|
47
|
+
.replace(/&/g, '-') // replace ampersands with dashes
|
|
48
|
+
.replace(/=/g, '-') // replace equals signs with dashes
|
|
49
|
+
.replace(/%/g, '-') // replace percent signs with dashes
|
|
50
|
+
.replace(/#/g, '-') // replace hash signs with dashes
|
|
51
|
+
.replace(/:/g, '-') // replace colons with dashes
|
|
52
|
+
.replace(/\+/g, '-') // replace plus signs with dashes
|
|
53
|
+
.replace(/ /g, '-') // replace spaces with dashes
|
|
54
|
+
.replace(/</g, '-') // replace less than signs with dashes
|
|
55
|
+
.replace(/>/g, '-') // replace greater than signs with dashes
|
|
56
|
+
.replace(/\*/g, '-') // replace asterisks with dashes
|
|
57
|
+
.replace(/\|/g, '-') // replace vertical bars with dashes
|
|
58
|
+
.replace(/"/g, '-') // replace double quotes with dashes
|
|
59
|
+
.replace(/'/g, '-') // replace single quotes with dashes
|
|
60
|
+
.replace(/\?/g, '-') // replace question marks with dashes
|
|
61
|
+
.replace(/\./g, '-') // replace dots with dashes
|
|
62
|
+
.replace(/,/g, '-') // replace commas with dashes
|
|
63
|
+
.replace(/;/g, '-') // replace semicolons with dashes
|
|
64
|
+
.replace(/\\/g, '-'); // replace backslashes with dashes
|
|
65
|
+
}
|
|
66
|
+
export { gcsCache };
|
package/dist/cache/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { memoryCache } from './memory.js';
|
|
2
2
|
import { s3Cache } from './s3.js';
|
|
3
|
+
import { gcsCache } from './gcs.js';
|
|
3
4
|
import { fileCache } from './file.js';
|
|
4
5
|
type Value = Buffer;
|
|
5
6
|
type Cache = {
|
|
@@ -8,4 +9,4 @@ type Cache = {
|
|
|
8
9
|
set: (key: string, value: Value) => Promise<void>;
|
|
9
10
|
};
|
|
10
11
|
declare const noneCache: () => Cache;
|
|
11
|
-
export { noneCache, memoryCache, s3Cache, fileCache, type Value, type Cache };
|
|
12
|
+
export { noneCache, memoryCache, s3Cache, gcsCache, fileCache, type Value, type Cache };
|
package/dist/cache/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { memoryCache } from './memory.js';
|
|
2
2
|
import { s3Cache } from './s3.js';
|
|
3
|
+
import { gcsCache } from './gcs.js';
|
|
3
4
|
import { fileCache } from './file.js';
|
|
4
5
|
const noneCache = () => ({
|
|
5
6
|
name: 'none',
|
|
6
7
|
get: async () => undefined,
|
|
7
8
|
set: async () => undefined,
|
|
8
9
|
});
|
|
9
|
-
export { noneCache, memoryCache, s3Cache, fileCache };
|
|
10
|
+
export { noneCache, memoryCache, s3Cache, gcsCache, fileCache };
|
package/dist/cli.js
CHANGED
|
@@ -21,6 +21,14 @@ function parseCacheStrategy(method, options) {
|
|
|
21
21
|
endpoint: options.s3Endpoint,
|
|
22
22
|
forcePathStyle: options.s3ForcePathStyle,
|
|
23
23
|
});
|
|
24
|
+
if (method === 'gcs')
|
|
25
|
+
return caches.gcsCache({
|
|
26
|
+
bucket: options.gcsCacheBucket,
|
|
27
|
+
projectId: options.gcsProjectId,
|
|
28
|
+
keyFilename: options.gcsKeyFilename,
|
|
29
|
+
prefix: options.gcsCachePrefix,
|
|
30
|
+
apiEndpoint: options.gcsApiEndpoint,
|
|
31
|
+
});
|
|
24
32
|
// command-line is not specified -> try to read from env
|
|
25
33
|
const cacheEnv = process.env.CHIITILER_CACHE_METHOD;
|
|
26
34
|
if (cacheEnv === 'memory')
|
|
@@ -40,6 +48,14 @@ function parseCacheStrategy(method, options) {
|
|
|
40
48
|
endpoint: process.env.CHIITILER_S3_ENDPOINT,
|
|
41
49
|
forcePathStyle: process.env.CHIITILER_S3_FORCE_PATH_STYLE === 'true',
|
|
42
50
|
});
|
|
51
|
+
if (cacheEnv === 'gcs')
|
|
52
|
+
return caches.gcsCache({
|
|
53
|
+
bucket: process.env.CHIITILER_GCS_CACHE_BUCKET ?? '',
|
|
54
|
+
prefix: process.env.CHIITILER_GCS_CACHE_PREFIX,
|
|
55
|
+
projectId: process.env.CHIITILER_GCS_PROJECT_ID,
|
|
56
|
+
keyFilename: process.env.CHIITILER_GCS_KEY_FILENAME,
|
|
57
|
+
apiEndpoint: process.env.CHIITILER_GCS_API_ENDPOINT,
|
|
58
|
+
});
|
|
43
59
|
// undefined or invalid
|
|
44
60
|
return caches.noneCache();
|
|
45
61
|
}
|
|
@@ -88,6 +104,11 @@ export function createProgram() {
|
|
|
88
104
|
.option('-s3b --s3-cache-bucket <bucket-name>', 's3 cache bucket name', '')
|
|
89
105
|
.option('-s3e --s3-endpoint <url>', 's3 endpoint url', '')
|
|
90
106
|
.option('-3p --s3-force-path-style', 's3 force path style', '')
|
|
107
|
+
.option('-gcsb --gcs-cache-bucket <bucket-name>', 'gcs cache bucket name', '')
|
|
108
|
+
.option('-gcsp --gcs-project-id <project-id>', 'gcs project id', '')
|
|
109
|
+
.option('-gcsk --gcs-key-filename <key-filename>', 'gcs key filename', '')
|
|
110
|
+
.option('-gcsp --gcs-cache-prefix <prefix>', 'gcs cache prefix', '')
|
|
111
|
+
.option('-gcse --gcs-api-endpoint <api-endpoint>', 'gcs api endpoint', '')
|
|
91
112
|
.option('-p --port <port>', 'port number')
|
|
92
113
|
.option('-r --stream', 'stream mode')
|
|
93
114
|
.option('-D --debug', 'debug mode')
|
|
@@ -101,6 +122,11 @@ export function createProgram() {
|
|
|
101
122
|
s3Region: options.s3Region,
|
|
102
123
|
s3Endpoint: options.s3Endpoint,
|
|
103
124
|
s3ForcePathStyle: options.s3ForcePathStyle === 'true',
|
|
125
|
+
gcsCacheBucket: options.gcsCacheBucket,
|
|
126
|
+
gcsCachePrefix: options.gcsCachePrefix,
|
|
127
|
+
gcsProjectId: options.gcsProjectId,
|
|
128
|
+
gcsKeyFilename: options.gcsKeyFilename,
|
|
129
|
+
gcsApiEndpoint: options.gcsApiEndpoint,
|
|
104
130
|
}),
|
|
105
131
|
port: parsePort(options.port),
|
|
106
132
|
debug: parseDebug(options.debug),
|
package/dist/gcs.d.ts
ADDED
package/dist/gcs.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Storage } from '@google-cloud/storage';
|
|
2
|
+
let storageClient; // singleton
|
|
3
|
+
const getStorageClient = function ({ projectId, keyFilename, apiEndpoint }) {
|
|
4
|
+
if (storageClient !== undefined)
|
|
5
|
+
return storageClient;
|
|
6
|
+
const storageOptions = {
|
|
7
|
+
projectId,
|
|
8
|
+
keyFilename,
|
|
9
|
+
apiEndpoint
|
|
10
|
+
};
|
|
11
|
+
storageClient = new Storage(storageOptions);
|
|
12
|
+
return storageClient;
|
|
13
|
+
};
|
|
14
|
+
export { getStorageClient };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getStorageClient } from '../gcs.js';
|
|
2
|
+
async function getGCSSource(uri) {
|
|
3
|
+
const storageClient = getStorageClient({
|
|
4
|
+
projectId: process.env.CHIITILER_GCS_PROJECT_ID,
|
|
5
|
+
keyFilename: process.env.CHIITILER_GCS_KEY_FILENAME,
|
|
6
|
+
apiEndpoint: process.env.CHIITILER_GCS_API_ENDPOINT,
|
|
7
|
+
});
|
|
8
|
+
const bucket = uri.replace('gs://', '').split('/')[0];
|
|
9
|
+
const path = uri.replace(`gs://${bucket}/`, '');
|
|
10
|
+
try {
|
|
11
|
+
const file = storageClient.bucket(bucket).file(path);
|
|
12
|
+
const [buffer] = await file.download();
|
|
13
|
+
return buffer;
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
if (e.code !== 404)
|
|
17
|
+
console.log(e);
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export { getGCSSource };
|
package/dist/source/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { getHttpSource } from './http.js';
|
|
|
3
3
|
import { getPmtilesSource } from './pmtiles.js';
|
|
4
4
|
import { getMbtilesSource } from './mbtiles.js';
|
|
5
5
|
import { getS3Source } from './s3.js';
|
|
6
|
+
import { getGCSSource } from './gcs.js';
|
|
6
7
|
import { getCogSource } from './cog.js';
|
|
7
8
|
import { noneCache } from '../cache/index.js';
|
|
8
9
|
/**
|
|
@@ -19,6 +20,8 @@ async function getSource(uri, cache = noneCache()) {
|
|
|
19
20
|
data = await getFilesystemSource(uri);
|
|
20
21
|
else if (uri.startsWith('s3://'))
|
|
21
22
|
data = await getS3Source(uri);
|
|
23
|
+
else if (uri.startsWith('gs://'))
|
|
24
|
+
data = await getGCSSource(uri);
|
|
22
25
|
else if (uri.startsWith('mbtiles://'))
|
|
23
26
|
data = await getMbtilesSource(uri);
|
|
24
27
|
else if (uri.startsWith('pmtiles://'))
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "chiitiler",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.15.0",
|
|
5
5
|
"description": "Tiny map rendering server for MapLibre Style Spec",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-s3": "^3.418.0",
|
|
36
|
+
"@google-cloud/storage": "^7.15.2",
|
|
36
37
|
"@hono/node-server": "^1.12.0",
|
|
37
38
|
"@mapbox/sphericalmercator": "^1.2.0",
|
|
38
39
|
"@mapbox/tilebelt": "^1.0.2",
|